home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / PlainText / PTDocs.c < prev    next >
Text File  |  1994-02-03  |  105KB  |  4,342 lines

  1. /*----------------------------- Includes ---------------------------------*/
  2.     
  3. #include "PlainText.h"
  4. #include "PTGlobs.h"
  5.  
  6. #pragma segment PTDocs
  7.  
  8. #define isneol(c) (c!='\n')
  9. #define iseol(c) (c=='\n')
  10.  
  11. /*--------------------------- Declarations -------------------------------*/
  12.  
  13. void nullWindowMethod(WindowPtr);
  14. int nullIntMethod(WindowPtr) ;
  15. void nullDraw(WindowPtr,Rect *,short);
  16. short nullShortMethod(WindowPtr);
  17.  
  18. int ConfirmDialog(short,Str255);
  19.  
  20. void focusOnWindow(WindowPtr);
  21. void focusOnContent(WindowPtr);
  22. void getContentRect(WindowPtr, Rect *);
  23.  
  24. pascal void doButton(DialogPtr,short);
  25. pascal void doFrame(DialogPtr,short);
  26. pascal void doLine(DialogPtr,short);
  27. Boolean InitScrollDoc(WindowPtr);
  28.  
  29. struct DocumentRecord *MakeDoc(OSType, FSSpecPtr);
  30. short getVertPageScrollAmount(WindowPtr);
  31. short getHorizPageScrollAmount(WindowPtr);
  32.  
  33. void AddMemberFunctions(DocumentPeek);
  34.  
  35. void destructor(WindowPtr);
  36. int DoClose(WindowPtr);
  37. void scrollDoGrow(WindowPtr,EventRecord *);
  38.  
  39. int doGrow(WindowPtr,EventRecord *);
  40. void doZoom(WindowPtr,short);
  41.  
  42. void doActivate(WindowPtr, EventRecord *);
  43. void activate(WindowPtr);
  44. void deactivate(WindowPtr);
  45.  
  46. void FillMarkMenu(DocumentPeek);
  47.  
  48. void SizeScrollBars(WindowPtr);
  49. void adjustScrollBars(WindowPtr);
  50. void setScrollBarValues(WindowPtr);
  51. void doContent(WindowPtr,EventRecord *);
  52. void ScrollClick(WindowPtr,EventRecord *);
  53. void DoButtonScroll(ControlHandle,Point);
  54. pascal void ActionProc(ControlHandle,short);
  55. void DoPageScroll(ControlHandle,short);
  56. void DoThumbScroll(ControlHandle,Point);
  57. void Scroll(ControlHandle,short);
  58. void CombinedScroll(WindowPtr,short,short);
  59. void doTheUpdate(WindowPtr, EventRecord *);
  60.  
  61. char *matchExpressionRight(char *,char *,int *,int *);
  62.  
  63. void AddText(WindowPtr,Ptr,long);
  64. void SetModDate(FSSpec *, unsigned long);
  65.  
  66. void textDraw(WindowPtr, Rect *,short);
  67. void textActivate(WindowPtr);
  68. void textDeactivate(WindowPtr);
  69. void textDoIdle(WindowPtr wind);
  70. void textAdjustCursor(WindowPtr,Point);
  71. void textDoKeyDown(WindowPtr,EventRecord *);
  72. void textDestructor(WindowPtr);
  73. void textSetScrollBarValues(WindowPtr);
  74. short textGetHorizSize(WindowPtr);
  75. short textGetVertSize(WindowPtr);
  76. void textGetContentRect(WindowPtr,Rect *);
  77. void textScrollContents(WindowPtr,short,short);
  78. short textGetVertLineScrollAmount(WindowPtr);
  79. short textGetHorizLineScrollAmount(WindowPtr);
  80. void textDoZoom(WindowPtr,short );
  81. void textDoGrow(WindowPtr,EventRecord *);
  82. void AddTextMemberFunctions(DocumentPeek);
  83. OSErr GetDirectoryFSSpec(short,long,ConstStr255Param,FSSpecPtr);
  84. void FindExpression(WindowPtr,char *);
  85. Boolean findSearchString(WindowPtr, short );
  86. int textWriteDocFile(WindowPtr);
  87. void textAdjustDocMenus(WindowPtr);
  88.  
  89.  
  90. void focusOnWindow(WindowPtr wind)
  91. {
  92.     Rect r;
  93.     
  94.     SetPort(wind);
  95.     SetOrigin(0,0);
  96.     r=wind->portRect;
  97.     ClipRect(&r);
  98. }
  99.  
  100. void focusOnContent(WindowPtr wind)
  101. {
  102.     Rect r;
  103.     
  104.     SetPort(wind);
  105.     SetOrigin(((DocumentPeek)wind)->hOffset,((DocumentPeek)wind)->vOffset);
  106.     GetContentRect(wind,&r);
  107.     ClipRect(&r);
  108. }
  109.  
  110. void getContentRect(WindowPtr wind, Rect *r)
  111. {
  112.     *r = wind->portRect;
  113.     if(((DocumentPeek)wind)->vScroll)
  114.         r->right-=15;
  115.     if(((DocumentPeek)wind)->hScroll)
  116.         r->bottom-=15;
  117. }
  118.     
  119. void doTheUpdate(WindowPtr wind, EventRecord *)
  120. {
  121.     Rect r;
  122.     if(((DocumentPeek)wind)->fDocWindow) {
  123.         FocusOnContent(wind);
  124.         BeginUpdate(wind);
  125.         r=(**(wind->visRgn)).rgnBBox;
  126.         (*((DocumentPeek)wind)->draw)(wind,&r,0);
  127.         FocusOnWindow(wind);
  128.         DrawControls(wind);
  129.         DrawGrowIcon(wind);
  130.         EndUpdate(wind);
  131.     }
  132. }
  133.  
  134. void nullDraw(WindowPtr,Rect *,short)
  135. {
  136.     return;
  137. }
  138.  
  139. int doGrow(WindowPtr wind,EventRecord *event)
  140. {
  141.     long        growResult;
  142.     Rect r;
  143.     
  144.     SetPort(wind);
  145.     growResult = GrowWindow(wind, event->where, &((DocumentPeek)wind)->limitRect);
  146.     
  147.     if (growResult) {                            /* has it really changed size? */
  148.         r = wind->portRect;
  149.         r.left = r.right-15;
  150.         InvalRect(&r);
  151.         
  152.         r = wind->portRect;    
  153.         r.top = r.bottom-15;
  154.         InvalRect(&r);
  155.  
  156.         SizeWindow(wind, LoWord(growResult), HiWord(growResult), TRUE);
  157.         
  158.         r = wind->portRect;
  159.         r.left = r.right-15;
  160.         InvalRect(&r);
  161.         
  162.         r = wind->portRect;
  163.         r.top = r.bottom-15;
  164.         InvalRect(&r);
  165.         
  166.         return 1;
  167.     }
  168.     return 0;
  169. }
  170.  
  171. void doZoom(WindowPtr wind,short partCode)
  172. {
  173.     SetPort(wind);
  174.     EraseRect(&wind->portRect);
  175.     ZoomWindow(wind,partCode,wind==FrontWindow());
  176.     InvalRect(&wind->portRect);
  177.     return;
  178. }
  179.  
  180. void doActivate(WindowPtr wind, EventRecord *event)
  181. {
  182.     if(((DocumentPeek)wind)->fDocWindow) {
  183.         if ((event->modifiers & activeFlag))              /* It's an activate  */
  184.             (*((DocumentPeek)wind)->activate)(wind);
  185.         else
  186.             (*((DocumentPeek)wind)->deactivate)(wind);
  187.     }
  188. }
  189.  
  190. void doContent(WindowPtr wind,EventRecord *event)
  191. {
  192.     Rect contents;
  193.     
  194.     FocusOnWindow(wind);
  195.     GlobalToLocal(&event->where);
  196.     GetContentRect(wind,&contents);
  197.     if(!PtInRect(event->where,&contents))
  198.         ScrollClick(wind,event);
  199. }
  200.  
  201. void activate(WindowPtr wind)
  202. {
  203.     FocusOnWindow(wind);
  204.     DrawGrowIcon(wind);
  205.     if(((DocumentPeek)wind)->hScroll)
  206.         ShowControl(((DocumentPeek)wind)->hScroll);
  207.     if(((DocumentPeek)wind)->vScroll)
  208.         ShowControl(((DocumentPeek)wind)->vScroll);
  209.     CurrentScrollDocument=(DocumentPeek)wind;
  210.     /* Each doc has its own copy of the markMenu */
  211.     DeleteMenu(MARK_ID);
  212.     MarkMenu=((DocumentPeek)wind)->markMenu;
  213.     if(MarkMenu)
  214.         InsertMenu(MarkMenu,WINDOW_ID);
  215.     AdjustMenus(wind);
  216.     DrawMenuBar();
  217.     return;
  218. }
  219.  
  220. void deactivate(WindowPtr wind)
  221. {
  222.     FocusOnWindow(wind);
  223.     DrawGrowIcon(wind);
  224.     if(((DocumentPeek)wind)->hScroll)
  225.         HideControl(((DocumentPeek)wind)->hScroll);
  226.     if(((DocumentPeek)wind)->vScroll)
  227.         HideControl(((DocumentPeek)wind)->vScroll);
  228.     return;
  229. }
  230.  
  231. void SizeScrollBars(WindowPtr wind)
  232. {
  233.     Rect r;
  234.     DocumentPeek doc;
  235.     
  236.     FocusOnWindow(wind);
  237.     r=wind->portRect;
  238.     doc = (DocumentPeek)wind;
  239.     if(doc->vScroll) {
  240.         SizeControl(doc->vScroll,16,r.bottom-r.top-15+2);
  241.         MoveControl(doc->vScroll,r.right-15,-1);
  242.         ValidRect(&(**doc->vScroll).contrlRect);
  243.     }
  244.     if(doc->hScroll) {
  245.         SizeControl(doc->hScroll,r.right-r.left-15+2,16);
  246.         MoveControl(doc->hScroll,-1,r.bottom-r.top-15);
  247.         ValidRect(&(**doc->hScroll).contrlRect);
  248.     }
  249. }
  250.  
  251. void adjustScrollBars(WindowPtr wind)
  252. {
  253.     DocumentPeek doc;
  254.     Rect r;
  255.     short dh,dv;
  256.     short currentValue;
  257.     short newMax;
  258.     RgnHandle oldClip;
  259.     
  260.     doc = (DocumentPeek)wind;
  261.     GetContentRect(wind,&r);
  262.     dh=dv=0;
  263.     if(doc->vScroll) {
  264.         currentValue=GetCtlValue(doc->vScroll);
  265.         newMax = GetVertSize(wind) - (r.bottom - r.top);
  266.         if(newMax<0)
  267.             newMax=0;
  268.         if(currentValue>newMax)
  269.             dv = currentValue - newMax;
  270.         SetCtlMax(doc->vScroll,newMax);
  271.     }
  272.     if(doc->hScroll) {
  273.         currentValue=GetCtlValue(doc->hScroll);
  274.         newMax = GetHorizSize(wind) - (r.right - r.left);
  275.         if(newMax<0)
  276.             newMax=0;
  277.         if(currentValue>newMax)
  278.             dh = currentValue - newMax;
  279.         SetCtlMax(doc->hScroll,newMax);
  280.     }
  281.     if(dh | dv) {
  282.         FocusOnContent(wind);
  283.         InvalRect(&r);
  284.         /* Shut down clip region to empty rectangle before calling
  285.             ScrollContents. */
  286.         oldClip = NewRgn();
  287.         GetClip(oldClip);
  288.         SetRect(&r,0,0,0,0);
  289.         ClipRect(&r);
  290.         ScrollContents(wind,dh,dv);
  291.         SetClip(oldClip);
  292.         DisposeRgn(oldClip);
  293.     }
  294. }
  295.  
  296. void setScrollBarValues(WindowPtr wind)
  297. {
  298.     DocumentPeek doc;
  299.     
  300.     FocusOnWindow(wind);
  301.     doc = (DocumentPeek)wind;
  302.     if(doc->hScroll)
  303.         SetCtlValue(doc->hScroll,doc->hOffset);    
  304.     if(doc->vScroll)
  305.         SetCtlValue(doc->vScroll,doc->vOffset);    
  306. }
  307.  
  308. void ScrollClick(WindowPtr wind,EventRecord *event)
  309. {
  310.     ControlHandle whichControl;
  311.     short part;
  312.     
  313.     FocusOnWindow(wind);
  314.     
  315.     if(part = FindControl(event->where,wind,&whichControl)) {
  316.         switch (part) {
  317.             case inThumb:
  318.                 DoThumbScroll(whichControl,event->where);
  319.                 break;
  320.             case inUpButton:
  321.             case inDownButton:
  322.                 DoButtonScroll(whichControl,event->where);
  323.                 break;
  324.             case inPageUp:
  325.             case inPageDown:
  326.                 DoPageScroll(whichControl,part);
  327.                 while(TickCount() < event->when+6) ;
  328.                 break;
  329.             default:
  330.                 break;
  331.         }
  332.     }
  333. }
  334.  
  335. void DoPageScroll(ControlHandle theControl,short part)
  336. {
  337.     short scrollAmount;
  338.     Point thePt;
  339.     short currentPart;
  340.     WindowPtr wind;
  341.         
  342.     wind = (**theControl).contrlOwner;
  343.     if(theControl == ((DocumentPeek)wind)->vScroll)
  344.         scrollAmount=(*((DocumentPeek)wind)->getVertPageScrollAmount)(wind);
  345.     else
  346.         scrollAmount=(*((DocumentPeek)wind)->getHorizPageScrollAmount)(wind);
  347.         
  348.     /* repeat as long as user holds down mouse button */
  349.     do {
  350.         GetMouse(&thePt);
  351.         if(part<0) 
  352.             currentPart=part=-part;
  353.         else
  354.             currentPart = TestControl(theControl,thePt);
  355.         if(currentPart == part) {
  356.             if(currentPart == inPageUp)
  357.                 Scroll(theControl,-scrollAmount);
  358.             if(currentPart == inPageDown)
  359.                 Scroll(theControl,scrollAmount);
  360.         }
  361.     } while (Button());
  362. }
  363.  
  364. void DoThumbScroll(ControlHandle theControl,Point localPt)
  365. {
  366.     short oldValue,trackResult,newValue,diff;
  367.     
  368.     WindowPtr wind;    
  369.     oldValue = GetCtlValue(theControl);
  370.     trackResult = TrackControl(theControl,localPt,NIL);
  371.     if(trackResult) {
  372.         newValue = GetCtlValue(theControl);
  373.         diff = oldValue - newValue;
  374.         wind = (**theControl).contrlOwner;
  375.         FocusOnContent(wind);
  376.         if(theControl==((DocumentPeek)wind)->hScroll)
  377.             ScrollContents(wind,diff,0);
  378.         if(theControl==((DocumentPeek)wind)->vScroll)
  379.             ScrollContents(wind,0,diff);
  380.         FocusOnWindow(wind);
  381.     }
  382. }
  383.     
  384. void Scroll(ControlHandle theControl,short change)
  385. {
  386.     /* Ref: p. 214 */
  387.     /* This should not have to be overridden (cf. p. 215). More likely, 
  388.         ScrollContents and SetScrollBarValues will be overridden. */
  389.         
  390.     WindowPtr wind;
  391.     RgnHandle oldClip;
  392.     long newValue;
  393.     short diff=0;
  394.     short oldValue;
  395.     short minValue,maxValue;
  396.     
  397.     oldClip=NewRgn();
  398.     GetClip(oldClip);
  399.     
  400.     oldValue = GetCtlValue(theControl);
  401.     newValue = oldValue + change;
  402.     
  403.     if(change<0) {
  404.         minValue = GetCtlMin(theControl);
  405.         if(newValue < minValue)
  406.             newValue = minValue;
  407.     } else {
  408.         maxValue = GetCtlMax(theControl);
  409.         if(newValue  > maxValue)
  410.             newValue = maxValue;
  411.     }
  412.     diff = oldValue - newValue;
  413.     wind = (**theControl).contrlOwner;
  414.     FocusOnContent(wind);
  415.     if(theControl == ((DocumentPeek)wind)->vScroll)
  416.         ScrollContents(wind,0,diff);
  417.     if(theControl == ((DocumentPeek)wind)->hScroll)
  418.         ScrollContents(wind,diff,0);
  419.         
  420.     FocusOnWindow(wind);
  421.     SetScrollBarValues(wind);
  422.     
  423.     SetClip(oldClip);
  424.     DisposeRgn(oldClip);
  425.  
  426. }
  427.  
  428. void CombinedScroll(WindowPtr wind,short dh,short dv)
  429. {
  430.     /* 
  431.         This is Scroll for both directions simultaneously. It could
  432.         be used for a hand tool (option-click). It is the working
  433.         routine for Display Selection. 
  434.     */
  435.         
  436.     DocumentPeek doc;
  437.     RgnHandle oldClip;
  438.     long newValue;
  439.     short diffH=0,diffV=0;
  440.     short oldValue;
  441.     short minValue,maxValue;
  442.     
  443.     oldClip=NewRgn();
  444.     GetClip(oldClip);
  445.     
  446.     doc=(DocumentPeek)wind;
  447.     
  448.     if(dh) {
  449.         oldValue = GetCtlValue(doc->hScroll);
  450.         newValue = oldValue + dh;
  451.     
  452.         if(dh<0) {
  453.             minValue = GetCtlMin(doc->hScroll);
  454.             if(newValue < minValue)
  455.                 newValue = minValue;
  456.         } else {
  457.             maxValue = GetCtlMax(doc->hScroll);
  458.             if(newValue  > maxValue)
  459.                 newValue = maxValue;
  460.         }
  461.         diffH = oldValue - newValue;
  462.     }
  463.     if(dv) {
  464.         oldValue = GetCtlValue(doc->vScroll);
  465.         newValue = oldValue + dv;
  466.     
  467.         if(dv<0) {
  468.             minValue = GetCtlMin(doc->vScroll);
  469.             if(newValue < minValue)
  470.                 newValue = minValue;
  471.         } else {
  472.             maxValue = GetCtlMax(doc->vScroll);
  473.             if(newValue  > maxValue)
  474.                 newValue = maxValue;
  475.         }
  476.         diffV = oldValue - newValue;
  477.     }
  478.         
  479.     ScrollContents(wind,diffH,diffV);
  480.         
  481.     FocusOnWindow(wind);
  482.     SetScrollBarValues(wind);
  483.     
  484.     SetClip(oldClip);
  485.     DisposeRgn(oldClip);
  486. }
  487.  
  488. void DoButtonScroll(ControlHandle theControl,Point localPt)
  489. {
  490.     short result;
  491.     
  492.     result = TrackControl(theControl,localPt,(ProcPtr)ActionProc);
  493. }
  494.  
  495. pascal void ActionProc(ControlHandle theControl,short partCode)
  496. {
  497.     short scrollAmount=0;
  498.     
  499.     if(theControl==CurrentScrollDocument->vScroll) 
  500.         scrollAmount = (*CurrentScrollDocument->getVertLineScrollAmount)((WindowPtr)CurrentScrollDocument);
  501.     if(theControl==CurrentScrollDocument->hScroll) 
  502.         scrollAmount = (*CurrentScrollDocument->getHorizLineScrollAmount)((WindowPtr)CurrentScrollDocument);
  503.     
  504.     if(partCode == inUpButton)    
  505.         Scroll(theControl,-scrollAmount);
  506.     if(partCode == inDownButton)    
  507.         Scroll(theControl,scrollAmount);
  508. }
  509.  
  510. void scrollContents(WindowPtr wind,short dh,short dv) 
  511. {
  512.     RgnHandle updateRgn;
  513.     Rect r;
  514.     
  515.     GetContentRect(wind,&r);
  516.     updateRgn = NewRgn();
  517.     ScrollRect(&r,dh,dv,updateRgn);
  518.     
  519.     ((DocumentPeek)wind)->hOffset -= dh;
  520.     ((DocumentPeek)wind)->vOffset -= dv;
  521.     
  522.     InvalRgn(updateRgn);
  523.     
  524.     DoTheUpdate(wind,(EventRecord *)nil);
  525.     
  526.     DisposeRgn(updateRgn);
  527. }
  528.  
  529. short getVertPageScrollAmount(WindowPtr wind)
  530. {
  531.     Rect r;
  532.     GetContentRect(wind,&r);
  533.     return r.bottom - r.top - 16;
  534. }
  535.  
  536. short getHorizPageScrollAmount(WindowPtr wind)
  537. {
  538.     Rect r;
  539.     GetContentRect(wind,&r);
  540.     return r.right - r.left - 16;
  541. }
  542.     
  543. short WantToSave(WindowPtr wind)
  544. {
  545.     Str255 title;
  546.     Str255 nullStr;
  547.     
  548.     *nullStr=0;
  549.     
  550.     if(((DocumentPeek)wind)->fDocWindow) {
  551.         GetWTitle(wind,title);
  552.         ParamText(title,nullStr,nullStr,nullStr);
  553.     } else
  554.         ParamText(nullStr,nullStr,nullStr,nullStr);
  555.     
  556.     return Alert(500,(ModalFilterProcPtr)nil);
  557. }
  558.  
  559. Boolean InitScrollDoc(WindowPtr wind)
  560. {
  561.     if(((DocumentPeek)wind)->fDocWindow) {
  562.         SetPort(wind);
  563.         ((DocumentPeek)wind)->hScroll = GetNewControl(128,wind);
  564.         ((DocumentPeek)wind)->vScroll = GetNewControl(129,wind);
  565.         SizeScrollBars(wind);
  566.         AdjustScrollBars(wind);
  567.         SetScrollBarValues(wind);
  568.     }
  569.     return(((DocumentPeek)wind)->hScroll && ((DocumentPeek)wind)->vScroll);
  570. }
  571.  
  572. #if 0
  573. void SelectWindowFromFile(short refnum)
  574. {
  575.     int i;
  576.     
  577.     for(i=0;i<MAXWINDS;i++) {
  578.         if(Documents[i].dataPathRefNum == refnum) {
  579.             if(Documents[i].fFileOpen && Documents[i].fDocWindow)
  580.                 SelectWindow((WindowPtr)(Documents+i));
  581.             else
  582.                 doMessage(2);
  583.             return;
  584.         }
  585.     }
  586.     doMessage(3);
  587. }
  588. #endif
  589.  
  590. void DetachDocResources(DocumentPeek doc)
  591. {
  592.     doc->windowState=0;
  593. }
  594.  
  595. Boolean openDocFile(WindowPtr wind)
  596. {
  597.     DocumentPeek doc;
  598.     short refnum, resRefnum;
  599.     OSErr err;
  600.     FSSpec specs;
  601.     long position;
  602.     
  603.     doc=(DocumentPeek)wind;
  604.     specs=doc->fileSpecs;
  605.     err = HOpen(specs.vRefNum,specs.parID,specs.name,fsCurPerm,&refnum); 
  606. /*    err = HOpen(specs.vRefNum,specs.parID,specs.name,fsRdWrPerm,&refnum); */
  607.     switch(err) {
  608.         case fnfErr:    /* file not found, create it */
  609.             err = HCreate(specs.vRefNum,specs.parID,specs.name,'MRPH',doc->fDocType);
  610.             if(err==noErr) {
  611.                 err = HOpen(specs.vRefNum,specs.parID,specs.name,fsCurPerm,&refnum);
  612.                 if(err!=noErr)
  613.                     return 0;
  614.             } else
  615.                 return 0;
  616.                 
  617.             // if open was successful, fall through to next case.
  618.             
  619.         case noErr:
  620.             doc->fFileOpen = true;
  621.             doc->dataPathRefNum = refnum;
  622.             break;
  623.         
  624.         case opWrErr:
  625.             /* 
  626.                 The file cannot be written into. It is already open in this
  627.                 or another application or it is on a locked volume.
  628.             */
  629.             doMessage(3);
  630.             doc->fFileOpen = true;
  631.             doc->fReadOnly = true;
  632.             doc->dataPathRefNum = refnum;
  633.             break;
  634.         case nsvErr:
  635.             /*    noSuchVolume error
  636.                 This error has occured in opening files from the finder in
  637.                 System 6, using multifinder. 
  638.             */
  639.             doMessage(16);
  640.             return 0;
  641.         default:
  642.             doDiagnosticMessage(13,err);    /* Unknown error */
  643.             return 0;
  644.     }
  645.     /* Successfull open. Now open any resource fork; */
  646.     
  647.     err = GetEOF(refnum,&position);
  648.     if(err==noErr) {
  649.         err = SetEOF(refnum,position);
  650.         switch(err) {
  651.             case noErr:    
  652.                 break;
  653.             case dskFulErr:    /* Disk is full */
  654.             case extFSErr:    /* File part of external file system */
  655.             case fnOpnErr:    /* File not open */
  656.             case ioErr:        /* I/O Error (bummers) */
  657.             case rfNumErr:    /* Bad reference number */
  658.                 break;
  659.             case fLckdErr:    /* File is locked */
  660.             case vLckdErr:    /* Software volume lock */
  661.             case wPrErr:    /* Diskette is locked */
  662.             case wrPermErr:    /* Write permission denied */
  663.                 doc->fReadOnly = true;
  664.                 break;
  665.             default:
  666.                 break;
  667.         }
  668.         
  669.     }
  670.     
  671.     resRefnum=HOpenResFile(specs.vRefNum,specs.parID,specs.name,fsCurPerm);
  672. /*    resRefnum=HOpenResFile(specs.vRefNum,specs.parID,specs.name,fsRdWrPerm); */
  673.     
  674.     if(resRefnum == -1) {
  675.         /* No resource fork for this file. */
  676.         doc->resourcePathRefNum=0;
  677.         if(!doc->fReadOnly) {
  678.             refnum=0;
  679.             err=ResError();
  680.     /*=============
  681.             switch (err) {
  682.             
  683.                 default:
  684.                     break;
  685.             }
  686.             ===============*/
  687.         
  688.             HCreateResFile(specs.vRefNum,specs.parID,specs.name);
  689.             err=ResError();
  690.             if(err!=noErr) {
  691.                 doMessage(17);
  692.             } else {
  693.                 refnum=HOpenResFile(specs.vRefNum,specs.parID,specs.name,fsCurPerm);
  694.                 doc->resourcePathRefNum=refnum;
  695.                 if(refnum==-1) {
  696.                     doc->resourcePathRefNum=refnum=0;
  697.                     doMessage(17);
  698.                     /* Can't create it. Forget this. */
  699.                 }
  700.             }
  701.         }
  702.     } else    
  703.         doc->resourcePathRefNum=resRefnum;
  704.         
  705.     return refnum;
  706. }
  707.  
  708. void MoveDocWindow(WindowPtr wind,short h,short v)
  709. {
  710.     if(((DocumentPeek)wind)->fDocWindow)
  711.         MoveWindow(wind,h,v,true);
  712. }
  713.  
  714. void CloseDocFile(DocumentPeek doc)
  715. {
  716.     OSErr err;
  717.     unsigned long modDate=0;
  718.     
  719.     if(doc->windowState) 
  720.         modDate = ((MPSRPtr)*doc->windowState)->modifiedDate;
  721.         
  722.     err = FSClose(doc->dataPathRefNum);
  723.     doc->dataPathRefNum=0;
  724.     if(doc->resourcePathRefNum) {
  725.         CloseResFile(doc->resourcePathRefNum);
  726.         doc->marks=0;
  727.         doc->windowState=0;
  728.         
  729.     }
  730.     doc->resourcePathRefNum=0;
  731.     
  732.     if(modDate) 
  733.         SetModDate(&doc->fileSpecs,modDate);
  734. }
  735.  
  736. void DeleteDoc(DocumentPeek doc)
  737. {
  738.     (*doc->destructor)((WindowPtr)doc);
  739. }
  740.  
  741. void SetDocWindowTitle(WindowPtr wind,Str255 title)
  742. {
  743.     if(((DocumentPeek)wind)->fDocWindow) 
  744.         SetWTitle(wind,title);
  745. }
  746.  
  747. void GetDocWindowTitle(WindowPtr wind,Str255 title)
  748. {
  749.     if(((DocumentPeek)wind)->fDocWindow) 
  750.         GetWTitle(wind,title);
  751. }
  752.  
  753. void ShowDocWindow(WindowPtr wind)
  754. {
  755.     if(((DocumentPeek)wind)->fDocWindow)
  756.         ShowWindow(wind);
  757. }
  758.  
  759. int DoSaveAs(WindowPtr wind)
  760. {
  761.     DocumentPeek doc;
  762.     StandardFileReply reply;
  763.     long response=0;
  764.     unsigned long modDate=0;
  765.     short resourcePathRefNum=0;
  766.     short dataPathRefNum=0;
  767.     OSErr err;
  768.     Boolean fFileOpen;
  769.     FSSpec existingFileInfo;
  770.     Str255 buf;
  771.         
  772.     doc = (DocumentPeek)wind;
  773.     GetIndString(buf,131,4);
  774.     if(Gestalt(gestaltStandardFileAttr,&response)==noErr)
  775.         StandardPutFile(buf,doc->fileSpecs.name,&reply);
  776.     else
  777.         glueStandardPutFile(buf,doc->fileSpecs.name,&reply);
  778.     
  779.     if(!reply.sfGood)                /* the user canceled the SaveAs */
  780.         return false;
  781.  
  782.  
  783.     if(fFileOpen=doc->fFileOpen) {
  784.         existingFileInfo=doc->fileSpecs;
  785.         dataPathRefNum=doc->dataPathRefNum;
  786.         resourcePathRefNum=doc->resourcePathRefNum;
  787.         if(doc->windowState)
  788.             modDate = ((MPSRPtr)*doc->windowState)->modifiedDate;
  789.     }
  790.  
  791.     doc->fileSpecs=reply.sfFile;
  792.  
  793.     if(!OpenDocFile(wind))    {        /* file didn't open */
  794.         doc->fileSpecs=existingFileInfo;
  795.         return false;
  796.     }
  797.     
  798.     if(resourcePathRefNum && doc->resourcePathRefNum) {
  799.         UseResFile(doc->resourcePathRefNum);
  800.         if(doc->windowState) {
  801.             DetachResource(doc->windowState);
  802.             AddResource(doc->windowState,'MPSR',1005,"");
  803.             WriteResource(doc->windowState);
  804.         }
  805.         if(doc->marks) {
  806.             DetachResource(doc->marks);
  807.             AddResource(doc->marks,'MPSR',1007,"");
  808.             WriteResource(doc->marks);
  809.         }
  810.     
  811.     }
  812.     
  813.     if(!WriteDocFile(wind)) {        /* write was unsuccessful */
  814.         doc->fileSpecs=existingFileInfo;
  815.         doc->fFileOpen=fFileOpen;
  816.         doc->resourcePathRefNum=resourcePathRefNum;
  817.         doc->dataPathRefNum=dataPathRefNum;
  818.         return false;
  819.     }
  820.     
  821.     doc->fNeedtoSaveAs=false;
  822.     doc->fNeedtoSave=false;
  823.     SetDocWindowTitle(wind,reply.sfFile.name);
  824.     
  825.     if(dataPathRefNum) {
  826.         err = FSClose(dataPathRefNum);
  827.         if(resourcePathRefNum)
  828.             CloseResFile(resourcePathRefNum);
  829.         if(modDate) 
  830.             SetModDate(&existingFileInfo,modDate);
  831.     }
  832.  
  833.     return true;
  834. }
  835.  
  836. int DoSaveACopy(WindowPtr wind)
  837. {
  838.     DocumentPeek doc;
  839.     StandardFileReply reply;
  840.     FSSpec existingFileInfo;
  841.     long response=0;
  842.     short resourcePathRefNum=0;
  843.     short dataPathRefNum=0;
  844.     Boolean fReadOnly=0;
  845.     OSErr err;
  846.     int ret=false;
  847.     Handle res,windowState,marks;
  848.     
  849.     EventMethod existingDoKeyDown;
  850.     IntMethod existingWriteDocFile;
  851.     WindowMethod existingAdjustDocMenus;
  852.  
  853.     Str255 buf;
  854.     
  855.     doc = (DocumentPeek)wind;
  856.     GetIndString(buf,131,5);
  857.     if(Gestalt(gestaltStandardFileAttr,&response)==noErr)
  858.         StandardPutFile(buf,doc->fileSpecs.name,&reply);
  859.     else
  860.         glueStandardPutFile(buf,doc->fileSpecs.name,&reply);
  861.     
  862.     if(!reply.sfGood) 
  863.         return false;
  864.         
  865.     existingFileInfo=doc->fileSpecs;
  866.     dataPathRefNum=doc->dataPathRefNum;
  867.     resourcePathRefNum=doc->resourcePathRefNum;
  868.     fReadOnly=doc->fReadOnly;
  869.     marks=doc->marks;
  870.     windowState=doc->windowState;
  871.     
  872.     existingDoKeyDown=doc->doKeyDown;
  873.     existingWriteDocFile=doc->writeDocFile;
  874.     existingAdjustDocMenus=doc->adjustDocMenus;
  875.  
  876.     doc->resourcePathRefNum=0;
  877.     doc->dataPathRefNum=0;
  878.     doc->fReadOnly=0;
  879.  
  880.     /*     doc->marks has been removed as a resource. We need a copy of its
  881.         data for the new file. The copy will become a resource and be
  882.         purged from memory. The orginal (**marks) is still good. */
  883.             
  884.     doc->fileSpecs=reply.sfFile;
  885.  
  886.     if(OpenDocFile(wind)) {    
  887.         if(resourcePathRefNum && doc->resourcePathRefNum) {    /* do both the original and new file have a resource fork? */
  888.             /*
  889.                 The following is not satisfactory. We want the saved file to have the marks and
  890.                 windowState as it stands now and we want to preserve it for the FrontWindow as
  891.                 well. The technique was to save them first.
  892.             */
  893. #if 0
  894.             if(doc->marks)
  895.                 ChangedResource(doc->marks);
  896.             if(doc->windowState)
  897.                 ChangedResource(doc->windowState);
  898.             UpdateResFile(resourcePathRefNum);
  899. #endif
  900.             UseResFile(doc->resourcePathRefNum);
  901.             if(res=windowState) {
  902.                 err=HandToHand(&res);
  903.                 if(err==noErr) {
  904.                     doc->windowState=res;
  905.                     AddResource(res,'MPSR',1005,"");
  906.                 } else
  907.                     doc->windowState=0;
  908.             }
  909.             if(res=marks) {
  910.                 err=HandToHand(&res);
  911.                 if(err==noErr) {
  912.                     doc->marks=res;
  913.                     AddResource(doc->marks,'MPSR',1007,"");
  914.                 } else
  915.                     doc->marks=0;
  916.             }
  917.         }
  918.         ret=WriteDocFile(wind);
  919.         CloseDocFile(doc);
  920.     }
  921.             
  922.     doc->fileSpecs=existingFileInfo;
  923.     doc->dataPathRefNum=dataPathRefNum;
  924.     doc->marks=marks;
  925.     doc->windowState=windowState;
  926.     doc->resourcePathRefNum=resourcePathRefNum;
  927.     doc->fReadOnly=fReadOnly; 
  928.     
  929.     doc->doKeyDown=existingDoKeyDown;
  930.     doc->writeDocFile=existingWriteDocFile;
  931.     doc->adjustDocMenus=existingAdjustDocMenus;
  932.  
  933. #if 0
  934.     if(doc->resourcePathRefNum=resourcePathRefNum) {
  935.         UseResFile(resourcePathRefNum);
  936.         doc->windowState=Get1Resource('MPSR',1005);
  937.         doc->marks=Get1Resource('MPSR',1007);
  938.     }
  939. #endif
  940.     return ret;
  941. }
  942.  
  943. int DoSave(WindowPtr wind)
  944. {
  945.     
  946.     if(((DocumentPeek)wind)->fNeedtoSaveAs) 
  947.         return DoSaveAs(wind);
  948.         
  949.     if(WriteDocFile(wind)) {
  950.         ((DocumentPeek)wind)->fNeedtoSave=false;
  951.         return true;
  952.     } else
  953.         return false;
  954. }
  955.  
  956. int DoClose(WindowPtr wind)
  957. {
  958.     short saveit;
  959.     
  960.     if(((DocumentPeek)wind)->fNeedtoSave) {
  961.         saveit = (wind==gPlainTextWSDoc)? iYes : WantToSave(wind);
  962.         if(saveit == iCancel)
  963.             return false;
  964.         if(saveit == iYes) {
  965.             if(!DoSave(wind))
  966.                 return false;
  967.         }
  968.     } else 
  969.         (*((DocumentPeek)wind)->writeDocResourceFork)(wind);
  970.     /*    close the file    */
  971.     if(((DocumentPeek)wind)->fFileOpen) {
  972.         CloseDocFile((DocumentPeek)wind);
  973.         ((DocumentPeek)wind)->fFileOpen=0;
  974.     }
  975.     return true;
  976. }
  977.  
  978. int DoRevert(WindowPtr wind)
  979. {
  980.     DocumentPeek doc;
  981.     Rect box;
  982.     Handle mH;
  983.     OSErr err;
  984.     
  985.     doc = (DocumentPeek)wind;
  986.     if(ConfirmDialog(6,doc->fileSpecs.name)) {
  987.         if(doc->marks) {
  988.             DetachResource(doc->marks);
  989.             DisposeHandle(doc->marks);
  990.             doc->marks=0;
  991.         }
  992.         if(doc->windowState) {
  993.             DetachResource(doc->windowState);
  994.             DisposeHandle(doc->windowState);
  995.             doc->windowState=0;
  996.         }
  997.         if(ReadDocFile(wind)) {
  998.             SetPort(wind);
  999.             GetContentRect(wind,&box);
  1000.             InvalRect(&box);
  1001.             EraseRect(&box);
  1002.             if(doc->marks)
  1003.                 FillMarkMenu(doc);
  1004.             else {
  1005.                 mH=GetResource('MENU',MARK_ID);
  1006.                 err=HandToHand(&mH);
  1007.                 if(err==noErr)
  1008.                     doc->markMenu=(MenuHandle)mH;
  1009.                 else
  1010.                     doc->markMenu=0;
  1011.             }
  1012.             doc->fNeedtoSave=false;
  1013.             return true;
  1014.         }
  1015.     } 
  1016.     return false;
  1017. }
  1018.  
  1019. void ClosePane(WindowPtr wind)
  1020. {
  1021.     WindowPtr doc;
  1022.     
  1023.     /* First remove this window from pane linked list. */
  1024.     doc=((DocumentPeek)wind)->homeWindow;
  1025.     while(doc && wind!=((DocumentPeek)doc)->associatedWindow)
  1026.         doc=((DocumentPeek)doc)->associatedWindow;
  1027.     if(!doc) 
  1028.         FatalError();
  1029.  
  1030.     ((DocumentPeek)doc)->associatedWindow=((DocumentPeek)wind)->associatedWindow;
  1031.     CloseWindow(wind);
  1032.     ((DocumentPeek)wind)->docData=NIL;
  1033.     ((DocumentPeek)wind)->fDocWindow=false;
  1034.     return;
  1035. }
  1036.  
  1037. /*----------------------------- Null Methods --------------------------------*/
  1038.  
  1039.  
  1040. void nullWindowMethod(WindowPtr) { return;}
  1041. void nullEventMethod(WindowPtr,EventRecord *) {return;}
  1042. void nullPointMethod(WindowPtr,Point) {return;}
  1043. short getLineScrollAmount(WindowPtr) {return 16;}
  1044. int nullIntMethod(WindowPtr) {return 1;}
  1045. short nullShortMethod(WindowPtr) {return 0;}
  1046.  
  1047. Boolean initDoc(WindowPtr) {return true;}
  1048.  
  1049. void destructor(WindowPtr wind)
  1050. {
  1051.     Handle mH;
  1052.     
  1053.     if(((DocumentPeek)wind)->fDocWindow) {
  1054.         CloseWindow(wind);
  1055.         NumWindows--;
  1056.     }
  1057.     
  1058.     mH=GetResource('MENU',MARK_ID);
  1059.     if(mH) {
  1060.         MarkMenu=(MenuHandle)mH;
  1061.         DeleteMenu(MARK_ID);
  1062.         InsertMenu(MarkMenu,WINDOW_ID);
  1063.     }
  1064.     
  1065.     if(((DocumentPeek)wind)->marks)
  1066.         DisposeHandle(((DocumentPeek)wind)->marks);
  1067.     if(((DocumentPeek)wind)->markMenu)
  1068.         DisposeHandle((Handle)((DocumentPeek)wind)->markMenu);
  1069.     if(((DocumentPeek)wind)->windowState)
  1070.         DisposeHandle(((DocumentPeek)wind)->windowState);
  1071.     if(((DocumentPeek)wind)->docData)
  1072.         DisposeHandle(((DocumentPeek)wind)->docData);
  1073.     ((DocumentPeek)wind)->fDocWindow=0;
  1074.     ((DocumentPeek)wind)->markMenu=0;
  1075.     ((DocumentPeek)wind)->windowState=0;
  1076.     ((DocumentPeek)wind)->docData=0;
  1077.  
  1078. }
  1079.  
  1080. /*-------------------------------- MakeDoc ----------------------------------
  1081.     MakeDoc finds the preallocated space for the document record, clears it,
  1082.     and initilizes it with (1) the member functions and (2) filetype and 
  1083.     FSSpec information. 
  1084. ----------------------------------------------------------------------------*/
  1085.  
  1086. DocumentPeek MakeDoc(OSType fType, FSSpecPtr fileSpecs)
  1087. {
  1088.     int i;
  1089.     DocumentPeek doc;
  1090.     Handle mH;
  1091.     OSErr err;
  1092.  
  1093.     for(i=0;i<MAXWINDS;i++) {
  1094.         if(Documents[i].fDocWindow==NIL) {
  1095.             doc=&Documents[i];
  1096.             memset(doc,0,sizeof(DocumentRecord));
  1097.             doc->fDocType=fType;
  1098.             if(fileSpecs)
  1099.                 doc->fileSpecs=*fileSpecs;
  1100.             mH=GetResource('MENU',MARK_ID);
  1101.             err=HandToHand(&mH);
  1102.             doc->markMenu=(MenuHandle)mH;
  1103.             AddMemberFunctions(doc);
  1104.             switch (fType) {
  1105.                 case 'TEXT':    /* also New */
  1106.                     AddTextMemberFunctions(doc);
  1107.                     break;
  1108.                 default:
  1109.                     break;
  1110.             }
  1111.             return doc;
  1112.         }
  1113.     }
  1114.     InitCursor();
  1115.     doMessage(4);    
  1116.     return 0;
  1117.  
  1118. }
  1119.  
  1120. Boolean makeWindow(WindowPtr wind)
  1121. {
  1122.     Rect r;
  1123.     short windowID;
  1124.     char *title;
  1125.     
  1126.     windowID=((DocumentPeek)wind)->windResource;
  1127.     
  1128.     SetRect(&r,DragBoundsRect.left+5+25*NumWindows,
  1129.                         DragBoundsRect.top+25+25*NumWindows,
  1130.                         DragBoundsRect.right-40,
  1131.                         DragBoundsRect.bottom);
  1132.     if ((r.right-r.left)>(1024+15)) r.right=r.left+1024+15;
  1133.     if ((r.bottom-r.top)>(1024+15)) r.bottom=r.top+1024+15;
  1134.     if(!((r.right-r.left)%2)) r.right--;
  1135.     if(!((r.bottom-r.top)%2)) r.bottom--;
  1136.     if(windowID) 
  1137.         wind=(gHasColorQD)?  GetNewCWindow(windowID,(void *)wind,(WindowPtr)-1L) :
  1138.                                 GetNewWindow(windowID,(void *)wind,(WindowPtr)-1L) ;
  1139.     else
  1140.         wind=(gHasColorQD)?  NewCWindow((void *)wind,&r,"",FALSE,zoomDocProc,(WindowPtr)-1L,TRUE,0) :
  1141.                                 NewWindow((void *)wind,&r,"",FALSE,zoomDocProc,(WindowPtr)-1L,TRUE,0);
  1142.     if(!wind)
  1143.         return 0;
  1144.     ((DocumentPeek)wind)->fDocWindow=true;    
  1145.     NumWindows++;
  1146.     if(title=((DocumentPeek)wind)->fileSpecs.name)
  1147.         SetDocWindowTitle(wind,title);    
  1148.     return true;
  1149.  
  1150. }
  1151.  
  1152. void adjustDocMenus(WindowPtr wind)
  1153. {
  1154.     DocumentPeek doc;
  1155.     
  1156.     doc=(DocumentPeek)wind;
  1157.     /* File Menu */
  1158.     EnableItem(FileMenu,iClose);
  1159.     SetMenuAbility(FileMenu,iSave,doc->fNeedtoSave);
  1160.     EnableItem(FileMenu,iSaveAs);
  1161.     EnableItem(FileMenu,iSaveACopy);
  1162.     SetMenuAbility(FileMenu,iRevert,doc->fNeedtoSave);
  1163.     EnableItem(FileMenu,iPageSetup);
  1164.     EnableItem(FileMenu,iPrint);
  1165.     
  1166.     /* Edit Menu */
  1167.     SetMenuAbility(EditMenu,iUndo,doc->fNeedtoSave);
  1168.     
  1169.     SetMenuAbility(EditMenu,iCut,doc->fHaveSelection);
  1170.     SetMenuAbility(EditMenu,iCopy,doc->fHaveSelection);
  1171.     EnableItem(EditMenu,iPaste);
  1172.     SetMenuAbility(EditMenu,iClear,doc->fHaveSelection);
  1173.  
  1174.     EnableItem(FileMenu,0);
  1175.     EnableItem(EditMenu,0);
  1176.     EnableItem(FindMenu,0);
  1177.     EnableItem(MarkMenu,0);
  1178.     EnableItem(WindowMenu,0);
  1179.     DisableItem(ConvertMenu,0);
  1180. }
  1181.  
  1182. void DoPageSetup(WindowPtr wind)
  1183. {
  1184.     PrOpen();
  1185.     PrStlDialog(((DocumentPeek)wind)->fPrintRecord);
  1186.     PrClose();
  1187. }
  1188.  
  1189. Boolean doDocMenuCommand(WindowPtr, short, short, short)
  1190. {    return false; }
  1191.  
  1192. /*  
  1193.     This is a menu function. Each Doc supplies its own method for this
  1194.     in its doDocMenuCommand method.
  1195. */
  1196.  
  1197. void AddMemberFunctions(DocumentPeek doc)
  1198. {
  1199.     doc->makeWindow=makeWindow;
  1200.     doc->initDoc=initDoc;
  1201.     doc->openDocFile=openDocFile;
  1202.     doc->destructor=destructor;
  1203.     /* Event actions */
  1204.     doc->doTheUpdate=doTheUpdate;
  1205.     doc->draw=nullDraw;
  1206.     doc->doActivate=doActivate;
  1207.     doc->activate=activate;
  1208.     doc->deactivate=deactivate;
  1209.     doc->doContent=doContent;
  1210.     doc->doKeyDown=nullEventMethod;
  1211.     doc->doIdle=nullWindowMethod;
  1212.     doc->adjustCursor=nullPointMethod;
  1213.     doc->doGrow=(EventMethod)doGrow;
  1214.     doc->doZoom=doZoom;
  1215.     
  1216.     /* Edit menu and clipboard functions */
  1217.     doc->doDocMenuCommand=doDocMenuCommand;
  1218.     doc->adjustDocMenus=adjustDocMenus;
  1219.     doc->doCut=nullWindowMethod;
  1220.     doc->doCopy=nullWindowMethod;
  1221.     doc->doPaste=nullWindowMethod;
  1222.     doc->doClear=nullWindowMethod;
  1223.     doc->doSelectAll=nullWindowMethod;
  1224.     doc->doUndo=nullWindowMethod;
  1225.     
  1226.     doc->readDocFile=nullIntMethod;
  1227.     doc->writeDocFile=nullIntMethod;
  1228.     doc->writeDocResourceFork=nullIntMethod;
  1229.     
  1230.     doc->fDocType='????';
  1231.  
  1232.     doc->doPageSetup=nullWindowMethod;
  1233.     doc->doPrint=nullWindowMethod;
  1234.     
  1235.     /* Scrolling methods */
  1236.     doc->adjustScrollBars=adjustScrollBars;
  1237.     doc->focusOnContent=focusOnContent;
  1238.     doc->focusOnWindow=focusOnWindow;
  1239.     doc->getVertSize=nullShortMethod;
  1240.     doc->getHorizSize=nullShortMethod;
  1241.     doc->getVertLineScrollAmount=getLineScrollAmount;
  1242.     doc->getHorizLineScrollAmount=getLineScrollAmount;
  1243.     doc->getVertPageScrollAmount=getVertPageScrollAmount;
  1244.     doc->getHorizPageScrollAmount=getHorizPageScrollAmount;
  1245.     
  1246.     doc->displaySelection=nullWindowMethod;
  1247.     
  1248.     doc->scrollContents=scrollContents;
  1249.     doc->setScrollBarValues=setScrollBarValues;
  1250.     doc->getContentRect=getContentRect;
  1251. }
  1252.  
  1253. void scrollDoGrow(WindowPtr wind,EventRecord *event)
  1254. {
  1255.     FocusOnWindow(wind);
  1256.     if(doGrow(wind,event)) {
  1257.         SizeScrollBars(wind);
  1258.         AdjustScrollBars(wind);
  1259.         SetScrollBarValues(wind);
  1260.     }
  1261. }
  1262.  
  1263. void scrollDoZoom(WindowPtr wind,short partCode)
  1264. {
  1265.     doZoom(wind,partCode);
  1266.     SizeScrollBars(wind);
  1267.     AdjustScrollBars(wind);
  1268.     SetScrollBarValues(wind);
  1269. }
  1270.  
  1271. pascal void doButton(DialogPtr wind,short)
  1272. {
  1273.     short itemType;
  1274.     Handle itemHand;
  1275.     Rect box;
  1276.  
  1277.     GetDItem(wind,1,&itemType,&itemHand,&box);
  1278.     PenSize(3,3);
  1279.     InsetRect(&box,-4,-4);
  1280.     FrameRoundRect(&box,16,16);
  1281. }
  1282.  
  1283. pascal void doFrame(DialogPtr wind,short item)
  1284. {
  1285.     short itemType;
  1286.     Handle itemHand;
  1287.     Rect box;
  1288.  
  1289.     GetDItem(wind,item,&itemType,&itemHand,&box);
  1290.     PenSize(1,1);
  1291.     FrameRect(&box);
  1292. }
  1293.  
  1294. pascal void doLine(DialogPtr wind,short item)
  1295. {
  1296.     short itemType;
  1297.     Handle itemHand;
  1298.     Rect box;
  1299.  
  1300.     GetDItem(wind,item,&itemType,&itemHand,&box);
  1301.     PenSize(1,1);
  1302.     MoveTo(box.left,box.top);
  1303.     LineTo(box.right,box.top);
  1304. }
  1305.  
  1306. void adjustCursor(WindowPtr, Point)
  1307. {    InitCursor();    }
  1308.  
  1309.  
  1310. #pragma segment TextViewDoc
  1311.  
  1312. /*---------------------------- TextWindow Object ----------------------------*/
  1313.  
  1314. void textDestructor(WindowPtr wind)
  1315. {
  1316.     WindowPtr sister;
  1317.     
  1318.     if((TE32KHandle)((DocumentPeek)wind)->docData) {
  1319.         TE32KDispose((TE32KHandle)((DocumentPeek)wind)->docData);
  1320.         ((DocumentPeek)wind)->docData=0;
  1321.         if(((DocumentPeek)wind)->associatedWindow) {
  1322.             sister = ((DocumentPeek)wind)->associatedWindow;
  1323.             if(StripAddress(((DocumentPeek)sister)->associatedWindow)==StripAddress(wind))
  1324.                 ((DocumentPeek)sister)->associatedWindow=0;
  1325.             ((DocumentPeek)wind)->associatedWindow=0;
  1326.         }
  1327.     }
  1328.     destructor(wind);
  1329. }
  1330.  
  1331. void textSetScrollBarValues(WindowPtr wind)
  1332. {
  1333.     TE32KHandle tH;
  1334.     LongRect visible,dest;
  1335.     long hPos=0,vPos=0,lineHeight;
  1336.     
  1337.     if(tH = (TE32KHandle)((DocumentPeek)wind)->docData) {
  1338.         visible = (**tH).viewRect;
  1339.         dest = (**tH).destRect;
  1340.         lineHeight = (**tH).lineHeight;
  1341.         vPos = (visible.top - dest.top)/lineHeight;
  1342.         hPos = (visible.left - dest.left);
  1343.     }
  1344.     FocusOnWindow(wind);
  1345.     SetCtlValue(((DocumentPeek)wind)->hScroll,(short)hPos);
  1346.     SetCtlValue(((DocumentPeek)wind)->vScroll,(short)vPos);
  1347. }
  1348.  
  1349. void textScrollContents(WindowPtr wind,short dh,short dv) 
  1350. {
  1351.     TE32KHandle tH;
  1352.     int lineHeight;
  1353.     
  1354.     if(tH=(TE32KHandle)((DocumentPeek)wind)->docData) {
  1355.         lineHeight = (**tH).lineHeight;
  1356.         TE32KScroll((long)dh,(long)dv*lineHeight,tH);
  1357.     }
  1358. }
  1359.  
  1360. short textGetVertLineScrollAmount(WindowPtr wind)
  1361. {
  1362.     if(((DocumentPeek)wind)->docData)
  1363.         return 1;
  1364.     else
  1365.         return 0;
  1366. }
  1367.  
  1368. short textGetHorizLineScrollAmount(WindowPtr wind)
  1369. {
  1370.     return (**((TE32KHandle)((DocumentPeek)wind)->docData)).theCharWidths['M'];
  1371. }
  1372.  
  1373. void textGetContentRect(WindowPtr wind,Rect *r)
  1374. {
  1375.     getContentRect(wind,r);
  1376.     r->left += 4;
  1377.     r->top    += 4;
  1378. }
  1379.  
  1380. short textGetVertSize(WindowPtr wind)
  1381. {
  1382.     return((**((TE32KHandle)((DocumentPeek)wind)->docData)).nLines);
  1383. }
  1384.  
  1385. short textGetHorizSize(WindowPtr wind)
  1386. {
  1387.     TE32KHandle tH;
  1388.     
  1389.     tH = (TE32KHandle)((DocumentPeek)wind)->docData;
  1390.         return (**tH).destRect.right - (**tH).destRect.left ;
  1391.         
  1392.     /*     Note that the destRect is the same as the viewRect when word
  1393.         wrapping to window. */
  1394. }
  1395.  
  1396. #if 0
  1397. void textPrintDraw(WindowPtr wind,Rect *r,short)
  1398. {
  1399.     TE32KHandle tH;
  1400.     short i,firstLine,lastLine;
  1401.     
  1402.     tH = (TE32KHandle)((DocumentPeek)wind)->docData;
  1403.     TextFont((**tH).txFont);
  1404.     TextSize((**tH).txSize);
  1405.     firstLine=r->top;
  1406.     lastLine=r->bottom;
  1407.     
  1408.     HLock((**tH).hText);
  1409.     for(i=firstLine;i<lastLine;i++) {
  1410.         MoveTo(LeftMargin,(**tH).lineHeight*(i-firstLine)+TopMargin+(**tH).fontAscent);
  1411.         DrawText(*(**tH).hText+(**tH).lineStarts[i],0,(**tH).lineStarts[i+1]-(**tH).lineStarts[i]);
  1412.     }
  1413.     HUnlock((**tH).hText);
  1414. }
  1415.  
  1416. #else
  1417.  
  1418. void textPrintDraw(WindowPtr wind,Rect *r,short page)
  1419. {
  1420.     long i,firstChar,lastChar;
  1421.     short firstLine,lastLine,vPos;
  1422.     long tabWidth;
  1423.     short pageWidth;
  1424.     unsigned char *textPtr;
  1425.     GrafPtr currentPort;
  1426.     TE32KHandle tH;
  1427.     Str31 numStr;
  1428.  
  1429.     tH = (TE32KHandle)((DocumentPeek)wind)->docData;
  1430.     
  1431.     GetPort(¤tPort);
  1432.     
  1433.     TextFont((**tH).txFont);
  1434.     TextFace((**tH).txFace);
  1435.     TextSize((**tH).txSize);
  1436.     TextMode((**tH).txMode);
  1437.                 
  1438.     firstLine=r->top;        /* zero indexed */
  1439.     lastLine=r->bottom;
  1440.     
  1441.     HLock((**tH).hText);
  1442.     textPtr = (unsigned char *) *((**tH).hText);
  1443.     tabWidth = (long)(**tH).tabWidth;
  1444.     
  1445.     vPos = TopMargin;
  1446.     
  1447.     while(firstLine<lastLine) {
  1448.         i=firstChar = (**tH).lineStarts[firstLine];
  1449.         lastChar = (**tH).lineStarts[firstLine+1];
  1450.         if (lastChar > firstChar && iseol(textPtr[lastChar-1]))
  1451.             lastChar--;
  1452.         MoveTo(LeftMargin,vPos);
  1453.         if((**tH).showInvisibles) {
  1454.             while (firstChar < lastChar) {
  1455.                 while (i<lastChar && textPtr[i]>=0x20 && !isspace(textPtr[i]))
  1456.                     i++;
  1457.  
  1458.                 if (i > firstChar)
  1459.                     DrawText(&(textPtr[firstChar]),0,(short) (i - firstChar));
  1460.                 
  1461.                 if(i<lastChar) {
  1462.                     if (textPtr[i]==TAB) {
  1463.                         DrawChar('Δ');
  1464.                         MoveTo(LeftMargin + ((currentPort->pnLoc.h - LeftMargin + tabWidth)/tabWidth)*tabWidth,currentPort->pnLoc.v);
  1465.                     } else if(textPtr[i]==' ')
  1466.                         DrawChar('◊');
  1467.                     else if(textPtr[i]=='\n')
  1468.                         DrawChar('¬');
  1469.                     else 
  1470.                         DrawChar('¿');
  1471.                     i++;
  1472.                 }
  1473.                 
  1474.                 firstChar = i;
  1475.                 
  1476.             }
  1477.             if(i<(**tH).teLength && textPtr[i]=='\n')
  1478.                 DrawChar('¬');
  1479.         } else {
  1480.             while (firstChar < lastChar) {
  1481.                 while (i<lastChar && textPtr[i]!=TAB)
  1482.                     i++;
  1483.                 
  1484.                 if (i > firstChar)
  1485.                     DrawText(&(textPtr[firstChar]),0,(short) (i - firstChar));
  1486.                 
  1487.                 if (i<lastChar && textPtr[i]==TAB) {
  1488.                     MoveTo(LeftMargin + ((currentPort->pnLoc.h - LeftMargin + tabWidth)/tabWidth)*tabWidth,currentPort->pnLoc.v);
  1489.                     i++;
  1490.                 }
  1491.                 
  1492.                 firstChar = i;
  1493.                 
  1494.             }
  1495.         }
  1496.         vPos += (**tH).lineHeight;
  1497.         firstLine++;
  1498.     }
  1499.     pageWidth=(**((DocumentPeek)wind)->fPrintRecord).prInfo.rPage.right;
  1500.     NumToString(page,numStr);
  1501.     pageWidth -= StringWidth(numStr);
  1502.     MoveTo(pageWidth/2,(**((DocumentPeek)wind)->fPrintRecord).prInfo.rPage.bottom);
  1503.     DrawString(numStr);
  1504.  
  1505.     HUnlock((**tH).hText);
  1506. }
  1507. #endif
  1508.  
  1509. void textDraw(WindowPtr wind, Rect *r,short page)
  1510. {
  1511.     LongRect lr;
  1512.     if(((DocumentPeek)wind)->docData) {
  1513.         if(page)                             /* Printing method */
  1514.             textPrintDraw(wind,r,page);
  1515.         else {
  1516.             EraseRect(r);
  1517.             RectToLongRect(r,&lr);
  1518.             TE32KUpdate(&lr,(TE32KHandle)((DocumentPeek)wind)->docData);
  1519.         }
  1520.     }
  1521. }
  1522.  
  1523. void textDoPrint(WindowPtr wind)
  1524. {
  1525.     TPPrPort printPort;
  1526.     TPrStatus status;
  1527.     TE32KHandle tH;
  1528.     short page,nPages;
  1529.     Rect r;
  1530.     short pageHeight,linesPerPage;
  1531.     short firstLine,lastLine;
  1532.     
  1533.     PrOpen();
  1534.     if(PrValidate(((DocumentPeek)wind)->fPrintRecord)) {
  1535.         if(!PrStlDialog(((DocumentPeek)wind)->fPrintRecord)) {
  1536.             PrClose();
  1537.             return;
  1538.         } 
  1539.     }
  1540.     if(!PrJobDialog(((DocumentPeek)wind)->fPrintRecord)) {
  1541.         PrClose();
  1542.         return;
  1543.     }
  1544.     printPort = PrOpenDoc(((DocumentPeek)wind)->fPrintRecord,nil,nil);
  1545.     tH = (TE32KHandle)((DocumentPeek)wind)->docData;
  1546.     
  1547.     pageHeight =(**((DocumentPeek)wind)->fPrintRecord).prInfo.rPage.bottom;
  1548.     linesPerPage=(pageHeight-TopMargin-BottomMargin)/(**tH).lineHeight;
  1549.     nPages=1+(**tH).nLines/linesPerPage;
  1550.         
  1551.     for(page=1;page<=nPages;page++) {
  1552.         firstLine=(page-1)*linesPerPage;
  1553.         if(firstLine<0) 
  1554.             firstLine=0;
  1555.         lastLine=firstLine+linesPerPage;
  1556.         if(lastLine>(**tH).nLines)
  1557.             lastLine=(**tH).nLines;
  1558.         r.top=firstLine;
  1559.         r.bottom=lastLine;
  1560.         PrOpenPage(printPort,nil);
  1561.         (*((DocumentPeek)wind)->draw)(wind,&r,page);
  1562.         PrClosePage(printPort);
  1563.     }
  1564.     PrCloseDoc(printPort);
  1565.     if((**((DocumentPeek)wind)->fPrintRecord).prJob.bJDocLoop != 0) 
  1566.         PrPicFile(((DocumentPeek)wind)->fPrintRecord,nil,nil,nil,&status);
  1567.     PrClose();
  1568. }
  1569.  
  1570. void textActivate(WindowPtr wind)
  1571. {
  1572.     activate(wind);
  1573.     if(((DocumentPeek)wind)->docData)
  1574.         TE32KActivate((TE32KHandle)((DocumentPeek)wind)->docData);
  1575. }
  1576.  
  1577. void textDeactivate(WindowPtr wind)
  1578. {
  1579.     deactivate(wind);
  1580.     if(((DocumentPeek)wind)->docData)
  1581.         TE32KDeactivate((TE32KHandle)((DocumentPeek)wind)->docData);
  1582. }
  1583.  
  1584. /* #define IDLE_DEBUG */
  1585.  
  1586. void textDoIdle(WindowPtr wind)
  1587. {
  1588.     GrafPtr oldPort;
  1589.     Point pt;
  1590.     
  1591. #ifdef IDLE_DEBUG
  1592. /*=============== Debug Code ===========*/
  1593.     TE32KHandle tH;
  1594.     DocumentPeek doc;
  1595.     MarkRecPtr theMark;
  1596.     long offset;
  1597.     char *p,*q;
  1598.  
  1599.     doc = (DocumentPeek)FrontLayer();
  1600.     tH = (TE32KHandle)((DocumentPeek)wind)->docData;
  1601.     if(tH && doc->marks) {
  1602.         theMark = (MarkRecPtr)(*doc->marks+2);
  1603.         offset = theMark->selStart;
  1604.         p=*(**tH).hText+offset;
  1605.         q=&theMark->label;
  1606.         if(*p != q[1])
  1607.             SysBeep(7);
  1608.     }
  1609. #endif
  1610.     
  1611.     if(((DocumentPeek)wind)->docData) 
  1612.         TE32KIdle((TE32KHandle)((DocumentPeek)wind)->docData);
  1613.     GetPort(&oldPort);
  1614.     SetPort(wind);
  1615.     GetMouse(&pt);
  1616.     (*((DocumentPeek)wind)->adjustCursor)(wind,pt);
  1617.     SetPort(oldPort);
  1618. }
  1619.  
  1620. void textAdjustCursor(WindowPtr wind,Point where)
  1621. {
  1622.     Rect r;
  1623.     CursHandle IBeam;
  1624.     
  1625.     GetContentRect(wind,&r);
  1626.     if(PtInRect(where,&r)) {
  1627.         IBeam = GetCursor(iBeamCursor);
  1628.         if(IBeam)
  1629.             SetCursor(*IBeam);
  1630.     } else
  1631.         InitCursor();
  1632. }
  1633.  
  1634. short SetSelectionFlag(TE32KHandle tH)
  1635. {
  1636.     long cr;
  1637.     
  1638.     if((**tH).selStart < (**tH).selEnd) {
  1639.         cr=Munger((**tH).hText,(**tH).selStart,"\n",1L,0,0);
  1640.         if(cr<0 || cr>=(**tH).selEnd)
  1641.             return 1;    /* no '\n' in selection range */
  1642.         return -1;        /* \n in selection range. */
  1643.     }
  1644.     return 0;            /* no selection range */
  1645. }
  1646.  
  1647. /*------------------------------- DoCommandLine -----------------------------------
  1648.     Here is the command parser for Vectors.
  1649.     
  1650.     At this time (v.0.7) command lines are passed in the global gCommandLine. This
  1651.     is not a bad idea as one might want to Unload most Vectors segments when doing
  1652.     a command.
  1653.     
  1654.     My list of essential commands to be implemented is short.
  1655.         1.    
  1656.         2.    dir/ls
  1657.         3.    open
  1658.         4.    target (open then BringToFront(Worksheet)
  1659.         5.    line (in target)
  1660.         6.    search
  1661.         7.    find
  1662.         8.    cd
  1663.         9.    close
  1664.         
  1665. ----------------------------------------------------------------------------------*/
  1666.  
  1667. void SelectLine(WindowPtr wind,long line)
  1668. {
  1669.     DocumentPeek doc;
  1670.     TE32KHandle tH;
  1671.     long selStart,selEnd,lastLine;
  1672.     GrafPtr oldPort;
  1673.     
  1674.     if(doc=(DocumentPeek)wind) {
  1675.         if((tH=(TE32KHandle)doc->docData) && 
  1676.                 (((WindowPeek)wind)->windowKind==9 || 
  1677.                     ((WindowPeek)wind)->windowKind==13)) {
  1678.             GetPort(&oldPort);
  1679.             SetPort(wind);
  1680.             lastLine=(**tH).nLines-1;
  1681.             /* Since nLines isn’t right if the last character is a return, check for that case.
  1682.                     (hint from TESample example. */
  1683.             if ( *(*(**tH).hText + (**tH).teLength - 1) == '\n' )
  1684.                 lastLine++;
  1685.             line=(line>lastLine)? lastLine: line;
  1686.             line=(line<=0)? 1 : line;
  1687.             selEnd = (**tH).lineStarts[line];
  1688.             selStart = (**tH).lineStarts[line-1];
  1689.             TE32KSetSelect(selStart,selEnd,tH);
  1690.             positionView(tH,1);
  1691.             AdjustScrollBars(wind);
  1692.             SetScrollBarValues(wind);
  1693.             doc->fHaveSelection = 1;
  1694.             SetPort(oldPort);
  1695.         }
  1696.     }
  1697. }
  1698.  
  1699. void FindExpression(WindowPtr wind,char *exp)
  1700. {
  1701.     DocumentPeek doc;
  1702.     TE32KHandle tH;
  1703.     GrafPtr oldPort;
  1704.     short oldSearchMethod,oldSearchBackwards,oldWrapSearch;
  1705.     Str255 oldFindBuffer;
  1706.     
  1707.     if(doc=(DocumentPeek)wind) {
  1708.         if((tH=(TE32KHandle)doc->docData) && 
  1709.                 (((WindowPeek)wind)->windowKind==9 || 
  1710.                     ((WindowPeek)wind)->windowKind==13)) {
  1711.             GetPort(&oldPort);
  1712.             
  1713.             oldSearchMethod=gSearchMethod;
  1714.             oldSearchBackwards = gSearchBackwards;
  1715.             oldWrapSearch = gWrapSearch;
  1716.  
  1717.             gSearchMethod = strpbrk(exp,"?*[≈")? 2:0;
  1718.             
  1719.             BlockMove(gFindBuffer,oldFindBuffer,*gFindBuffer+1);
  1720.             exp=ConditionFileName(exp);
  1721.             strcpy(gFindBuffer,exp);
  1722.             c2pstr(gFindBuffer);
  1723.             gSearchBackwards = false;
  1724.             gWrapSearch = false;
  1725.             if(!findSearchString(wind,0)) {
  1726.                 gSearchMethod=oldSearchMethod;
  1727.                 gSearchBackwards = oldSearchBackwards;
  1728.                 gWrapSearch = oldWrapSearch;
  1729.                 BlockMove(oldFindBuffer,gFindBuffer,*oldFindBuffer+1);
  1730.             }
  1731.             SetPort(oldPort);
  1732.         }
  1733.     }
  1734. }
  1735.  
  1736. void MakeTargetWindow(WindowPtr wind)
  1737. {
  1738.     WindowPtr front;
  1739.     
  1740.     if(wind!=TargetWindow()) {
  1741.         front = FrontLayer();
  1742.         if(wind!=front) {                                /* wind has to be brought closer to the front */
  1743.             PaintOne((WindowPeek)wind,((WindowPeek)wind)->strucRgn);
  1744.             CalcVis((WindowPeek)wind);
  1745.             SendBehind(wind,front);
  1746.         } else if(front=(WindowPtr)((WindowPeek)wind)->nextWindow) /* it is the front window and there is more than one window */
  1747.             SelectWindow(front);
  1748.     }
  1749. }
  1750.  
  1751. Boolean WildCardMatch(char *tok,char *exp)
  1752. {
  1753.     int foundLen=0,n2=0;
  1754.     
  1755.     *(tok+*tok+1) = '\0';
  1756.     /*     
  1757.         MatchExpressionRight is a search routine that returns a match
  1758.         anywhere in tok. We want a perfect match, where tok is identical
  1759.         to the found string.
  1760.     */
  1761.     return (matchExpressionRight(tok+1,exp,&foundLen,&n2) && foundLen==*tok);
  1762. }
  1763.  
  1764. Boolean CheckForFlag(char *str,char *flag,long len)
  1765. {
  1766.     char *ret;
  1767.     ret = strstr(str,flag);
  1768.     return (ret)? isspace(*(ret+len)) || !*(ret+len) : false;
  1769. }
  1770.  
  1771. char *ConditionFileName(char *str)
  1772. {    
  1773.     char *p,*ret;
  1774.     
  1775.     p=str;
  1776.     while(*p) {
  1777.         while(isspace(*p)) p++;
  1778.         if(*p=='-') {
  1779.             p++;
  1780.             while(isalnum(*p)) p++;
  1781.         } else if(*p) {
  1782.             if(*p=='"' || *p=='\'') {
  1783.                 ret=p++;
  1784.                 while(*p && *p!=*ret) p++;
  1785.                 if(*p) {
  1786.                     *p='\0';
  1787.                     return ret+1;
  1788.                 } else
  1789.                     return 0;
  1790.             } else {
  1791.                 ret=p;
  1792.                 while(isgraph(*p)) p++;
  1793.                 *p='\0';
  1794.                 return ret;
  1795.             }
  1796.         }
  1797.     }
  1798.     return 0;
  1799. }
  1800.  
  1801. void PrintBuf(Str255 buf,long length,DocumentPeek doc)
  1802. {
  1803.     TE32KHandle tH;
  1804.     
  1805.     if(!doc)
  1806.         doc=gPlainTextWSDoc;
  1807.     if(doc) {
  1808.         tH = (TE32KHandle)doc->docData;
  1809.         TE32KInsert(buf,length,tH);
  1810.         doc->fNeedtoSave = true;
  1811.     }
  1812. }
  1813.  
  1814. void PrintFileName(WindowPtr wind,HFileInfo *pB,char *path)
  1815. {
  1816.     int k=0,quote;
  1817.     Str255 buf;
  1818.     
  1819.     p2cstr(pB->ioNamePtr);
  1820.     
  1821.     quote=*path || strchr(pB->ioNamePtr,' ');
  1822.     if(quote) {    /* Need to quote */
  1823.         *buf='\'';
  1824.         k++;
  1825.     }
  1826.     if(!*path && pB->ioFlAttrib&16)        /* It's a directory    */
  1827.         *(buf+k++)=':';
  1828.     if(*path)
  1829.         k+=sprintf(buf+k,"%s",path);
  1830.     k+=sprintf(buf+k,"%s",pB->ioNamePtr);
  1831.     if(pB->ioFlAttrib&16)                /* It's a directory    */
  1832.         *(buf+k++)=':';
  1833.     if(quote)
  1834.         *(buf+k++)='\'';
  1835.     *(buf+k++)='\n';
  1836.     *(buf+k)='\0';
  1837.     PrintBuf(buf,k,(DocumentPeek)wind);
  1838. }
  1839.  
  1840. PrintLongFormat(WindowPtr wind,HFileInfo *pB)
  1841. {
  1842.     int k,hour;
  1843.     DateTimeRec date;
  1844.     char dateStr[12];
  1845.     Str255 buf;
  1846.     
  1847.     p2cstr(pB->ioNamePtr);
  1848.     memset(buf,' ',21);
  1849.     if(strchr(pB->ioNamePtr,' ')) 
  1850.         k=sprintf(buf,"'%s'",pB->ioNamePtr);
  1851.     else
  1852.         k=sprintf(buf,"%s",pB->ioNamePtr);
  1853.     if(k<21)
  1854.         *(buf+k)=' ';
  1855.     else
  1856.         *(buf+20)='…';
  1857.     k=21;
  1858.     if(pB->ioFlAttrib&16)        /* It's a directory */
  1859.         k+=sprintf(buf+k," Fldr Fldr");
  1860.     else
  1861.         k+=sprintf(buf+k," %4.4s %4.4s",&pB->ioFlFndrInfo.fdType,&pB->ioFlFndrInfo.fdCreator);
  1862.         
  1863.     k+=sprintf(buf+k,"%6dK",(pB->ioFlPyLen+pB->ioFlRPyLen)/1024);
  1864.     Secs2Date(pB->ioFlMdDat,&date);
  1865.     sprintf(dateStr,"%d/%d/%02d",date.month,date.day,date.year%100);
  1866.     k+=sprintf(buf+k,"%11s",dateStr);
  1867.     hour=(date.hour>12)? date.hour-12:date.hour;
  1868.     if(hour==0)
  1869.         hour=12;
  1870.     k+=sprintf(buf+k,"%3d:%02d %s",hour,date.minute,(date.hour>12)?"PM":"AM");
  1871.  
  1872.     Secs2Date(pB->ioFlCrDat,&date);
  1873.     sprintf(dateStr,"%d/%d/%02d",date.month,date.day,date.year&100);
  1874.     k+=sprintf(buf+k,"%11s",dateStr);
  1875.     hour=(date.hour>12)? date.hour-12:date.hour;
  1876.     k+=sprintf(buf+k,"%3d:%02d %s",hour,date.minute,(date.hour>12)?"PM":"AM");
  1877.     k+=sprintf(buf+k,"\n");
  1878.     PrintBuf(buf,k,(DocumentPeek)wind);
  1879. }
  1880.  
  1881. void CommandLineError(short errNum)
  1882. {
  1883.     if(errNum) {
  1884.         ;
  1885.     } else
  1886.         SysBeep(7);
  1887. }
  1888.  
  1889. void ChangeDirectory(char *dirName)
  1890. {
  1891.     OSErr err;
  1892.     FSSpec spec;
  1893.     char *p;
  1894.     
  1895.     p=ConditionFileName(dirName);    
  1896.     if(!p || !*p)
  1897.         return;
  1898.  
  1899.     c2pstr(p);
  1900.     err=GetDirectoryFSSpec(DefaultSpecs.vRefNum,DefaultSpecs.parID,p,&spec);
  1901.     /*    The problem here is that the parent directory was returned. For
  1902.         directories, this is one level too high. */
  1903.     if(err==noErr) 
  1904.         DefaultSpecs=spec;
  1905.     else
  1906.         CommandLineError(0);
  1907. }
  1908.  
  1909. OSErr GetVolRefNum(char *name,short *volID)
  1910. {    
  1911.     OSErr err;
  1912.     HVolumeParam pB;
  1913.     Str255 temp;
  1914.     
  1915.     memset(&pB,0,sizeof(HVolumeParam));
  1916.     if(*name)
  1917.         BlockMove(name,temp,*name+1);
  1918.     else
  1919.         *temp='\0';
  1920.     pB.ioNamePtr=temp;
  1921.     pB.ioVolIndex=-1;
  1922.     err=PBHGetVInfoSync((HParmBlkPtr)&pB);
  1923.     *volID=pB.ioVRefNum;
  1924.     return err;
  1925. }
  1926.     
  1927. int AscendTheTree(short vRefNum,long dirID,char *buf,int k)
  1928. {
  1929.     OSErr err;
  1930.     Str63 name;
  1931.     HFileInfo pB;
  1932.  
  1933.     if(dirID==1)
  1934.         return k;
  1935.     memset(&pB,0,sizeof(HFileInfo));
  1936.     pB.ioDirID=dirID;
  1937.     pB.ioVRefNum=vRefNum;
  1938.     pB.ioNamePtr=name;
  1939.     pB.ioFDirIndex=-1;
  1940.     err=PBGetCatInfoSync((CInfoPBPtr)&pB);
  1941.     if(err!=noErr)
  1942.         return 0;
  1943.     if(dirID==2)
  1944.         return sprintf(buf,"%s:",p2cstr(name));
  1945.     k=AscendTheTree(vRefNum,pB.ioFlParID,buf+k,k);
  1946.     k+=sprintf(buf+k,"%s:",p2cstr(name));
  1947.     return k;
  1948. }
  1949.  
  1950. OSErr GetDirectoryFSSpec(short volRefNum,long dirID,
  1951.                         ConstStr255Param fileName,FSSpecPtr spec)
  1952. {
  1953.     OSErr err;
  1954.     short newVolRefNum;
  1955.     long newDirID;
  1956.     HFileInfo pB;
  1957.     Str255 temp;
  1958.  
  1959.     err=GetWDInfo(volRefNum,&newVolRefNum,&newDirID,0);
  1960.     if(err==noErr) {
  1961.         dirID=(dirID)?dirID:newDirID;
  1962.         volRefNum=newVolRefNum;
  1963.     }
  1964.     
  1965.     if(*fileName) {
  1966.         /*    There is a pathname. */
  1967.         BlockMove(fileName,temp,*fileName+1);
  1968.         *(temp+*fileName+1)='\0';
  1969.         if(isfullpath(temp+1)) {
  1970.             err=GetVolRefNum(temp,&volRefNum);
  1971.             if(err!=noErr) {
  1972.                 BlockMove(temp,spec->name,*temp+1);
  1973.                 return err;
  1974.             }
  1975.             BlockMove(fileName,temp,*fileName+1);
  1976.             *(temp+*fileName+1)='\0';
  1977.         }
  1978.     } else
  1979.         *temp=0;
  1980.     
  1981.     memset(&pB,0,sizeof(HFileInfo));
  1982.     pB.ioNamePtr=temp;
  1983.     pB.ioDirID=dirID;
  1984.     pB.ioVRefNum=volRefNum;
  1985.     
  1986.     if(*temp) {
  1987.         /*  PBGetCatInfo with pB.ioFDirIndex==0 doesn't work if there
  1988.             is no file name. */
  1989.         err=PBGetCatInfoSync((CInfoPBPtr)&pB);
  1990.         if(err!=noErr)
  1991.             return err;
  1992.         if(!(pB.ioFlAttrib&16)) {
  1993.             /*    Whether we have returned a directory or not, we still need
  1994.                 the correct directory name. The dirID is in the parID if we
  1995.                 have returned a file. */
  1996.             pB.ioDirID=pB.ioFlParID;
  1997.         }
  1998.     }
  1999.     pB.ioFDirIndex=-1;
  2000.     *temp=0;
  2001.     err=PBGetCatInfoSync((CInfoPBPtr)&pB);
  2002.     spec->vRefNum=pB.ioVRefNum;
  2003.     spec->parID=pB.ioDirID;
  2004.     BlockMove(temp,spec->name,*temp+1);
  2005.     return err;
  2006. }
  2007.  
  2008. void FillPathName(char *buf,char *name)
  2009. {
  2010.     FSSpec spec;
  2011.     OSErr err;
  2012.     Str255 path;
  2013.     
  2014.     if(name) {
  2015.         strcpy(path,name);
  2016.         c2pstr(path);
  2017.     } else
  2018.         *path='\0';
  2019.         
  2020.     *buf='\0';
  2021.     err=GetDirectoryFSSpec(DefaultSpecs.vRefNum,DefaultSpecs.parID,path,&spec);
  2022.     if(err==noErr)
  2023.         AscendTheTree(spec.vRefNum,spec.parID,buf,0);
  2024. }
  2025.  
  2026. void Directory(WindowPtr wind,Str255 args)
  2027. {
  2028.     short i,volRefNum;
  2029.     long dirID,k;
  2030.     Boolean fFullPath,fLongFormat;
  2031.     char *fWildCards;
  2032.     HFileInfo pB;
  2033.     OSErr err;
  2034.     Str63 exp;
  2035.     Str255 name,path;
  2036.     char *fileName;
  2037.     
  2038.     fFullPath=CheckForFlag(args,"-f",2);
  2039.     fLongFormat=CheckForFlag(args,"-l",2);
  2040.     fileName=ConditionFileName(args);
  2041.     
  2042.     if(fWildCards=(fileName)?strpbrk(fileName,"?*[≈"):false) {
  2043.         fWildCards=strrchr(fileName,':');
  2044.         fWildCards=(fWildCards)? fWildCards+1:fileName;
  2045.         strcpy(exp,fWildCards);
  2046.         *fWildCards='\0';            /* Remove wildcard part from fileName */
  2047.     }
  2048.  
  2049.     if(fLongFormat) {
  2050.         k=sprintf(name,"Name                  Type Crtr  Size       Last-Mod-Date       Creation-Date \n");
  2051.         PrintBuf(name,k,(DocumentPeek)wind);
  2052.         k=sprintf(name,"--------------------  ---- ---- ------ ------------------- -------------------\n");
  2053.         PrintBuf(name,k,(DocumentPeek)wind);
  2054.     }
  2055.         
  2056.     if(fFullPath)
  2057.         FillPathName(path,fileName);
  2058.     else
  2059.         *path='\0';
  2060.         
  2061.     memset(&pB,0,sizeof(HFileInfo));
  2062.     
  2063.     dirID=DefaultSpecs.parID;
  2064.     volRefNum=DefaultSpecs.vRefNum;
  2065.     if(fileName && *fileName) {
  2066.         c2pstr(fileName);
  2067.         *(fileName+*fileName+1)='\0';
  2068.         if(isfullpath(fileName+1)) {
  2069.             err=GetVolRefNum(fileName,&volRefNum);
  2070.             if(err!=noErr)
  2071.                 return;
  2072.         }
  2073.         pB.ioDirID=dirID;
  2074.         pB.ioVRefNum=volRefNum;
  2075.         pB.ioNamePtr=fileName;
  2076.         if((err=PBGetCatInfoSync((CInfoPBPtr)&pB))==noErr) {
  2077.             if(pB.ioFlAttrib&16) {        /* It's a directory */
  2078.                 dirID=pB.ioDirID;
  2079.                 volRefNum=pB.ioVRefNum;
  2080.             } else if(!fWildCards || WildCardMatch(pB.ioNamePtr,exp)) {    /* It's a file */
  2081.                 if(fLongFormat)
  2082.                     PrintLongFormat(wind,&pB);
  2083.                 else
  2084.                     PrintFileName(wind,&pB,path);
  2085.                 return;
  2086.             }
  2087.         } else
  2088.             return;
  2089.     }
  2090.     /* list an entire directory */
  2091.     fileName=name;
  2092.     for(i=1,err=0;err==noErr;i++) {
  2093.         *fileName=0;
  2094.         pB.ioDirID=dirID;
  2095.         pB.ioVRefNum=volRefNum;
  2096.         pB.ioFDirIndex = i;
  2097.         pB.ioNamePtr=fileName;
  2098.         if((err=PBGetCatInfoSync((CInfoPBPtr)&pB))==noErr) {
  2099.             if(!fWildCards || WildCardMatch(pB.ioNamePtr,exp)) {
  2100.                 if(fLongFormat)
  2101.                     PrintLongFormat(wind,&pB);
  2102.                 else
  2103.                     PrintFileName(wind,&pB,path);
  2104.             }
  2105.         }
  2106.     }
  2107. }
  2108.  
  2109. void DoCommandLine(WindowPtr wind)
  2110. {
  2111.     char *s,*arg,*p;
  2112.     long value;
  2113.     WindowPtr newWind;
  2114.     
  2115.     s=gCommandLine;
  2116.     do {
  2117.         while(isspace(*s)) s++;                        /* s points to command */
  2118.         
  2119.         for(arg=s;isgraph(*arg);arg++) ;    /* arg point to argument(s) */
  2120.         while(isspace(*arg)) arg++;
  2121.         
  2122.         for(p=arg;*p && *p!=';';p++) ;                /* p points to end of command */
  2123.         if(*p==';')
  2124.             *p++='\0';
  2125.         
  2126.         switch (tolower(*s)) {
  2127.             case 'c':
  2128.                 if(s[1]=='d' && isspace(s[2])) 
  2129.                     ChangeDirectory(arg);
  2130.                 break;
  2131.             case 'f':
  2132.                 if(!strncmp(s+1,"ile",3) && isspace(s[4])) {
  2133.                     gTextWindowPosition=wind;
  2134.                     newWind=OpenNamedFile(arg);
  2135.                     textDeactivate(newWind);
  2136.                 } else if(!strncmp(s+1,"ind",3) && isspace(s[4])) 
  2137.                     FindExpression(TargetWindow(),arg);
  2138.                 break;
  2139.             case 'l':
  2140.                 if(tolower(s[1])=='s' && (!s[2] || isspace(s[2]))) 
  2141.                     Directory(wind,arg);
  2142.                 else if(!strncmp(s+1,"ine",3) && (!s[4] || isspace(s[4]))) {
  2143.                     value = atoi(arg);
  2144.                     SelectLine(TargetWindow(),value);
  2145.                 }
  2146.                 break;
  2147.             case 'o':
  2148.                 if(!strncmp(s+1,"pen",3) && isspace(s[4])) {
  2149.                     if(newWind=OpenNamedFile(arg))
  2150.                         SelectWindow(newWind);
  2151.                 }
  2152.                 break;
  2153.             case ';':
  2154.                 p++;
  2155.                 break;
  2156.             default:
  2157.                 break;
  2158.         }
  2159.     } while(*(s=p));
  2160.     
  2161.     TE32KSelView((TE32KHandle)((DocumentPeek)wind)->docData);
  2162.     AdjustScrollBars(wind);
  2163.     SetScrollBarValues(wind);
  2164. }
  2165.  
  2166. void textDoKeyDown(WindowPtr wind,EventRecord *theEvent)
  2167. {
  2168.     int commandLen=0,tokenStart,tokenEnd,teLength;
  2169.     Boolean fCommandIsSelection=false,result;
  2170.     unsigned char *s, ch;
  2171.     TE32KHandle tH;
  2172.     long selStart,selEnd,delta;
  2173.     
  2174.     if(tH=(TE32KHandle)((DocumentPeek)wind)->docData) {
  2175.         ch=theEvent->message&charCodeMask;
  2176.         if(ch==3) {        /* ENTER character */
  2177.         
  2178.             /*
  2179.             If there is a selection, pass it to the command parser and make no 
  2180.             change to selection range. If there is no selection (selEnd==selStart), 
  2181.             pass the whole line to the command parser and add a newline to the end 
  2182.             of the line.
  2183.             */
  2184.             
  2185.         /*    xorCaret(tH);    */
  2186.         
  2187.             HLock((**tH).hText);
  2188.             tokenEnd = (**tH).selEnd;
  2189.             tokenStart = (**tH).selStart;
  2190.             commandLen = tokenEnd - tokenStart;
  2191.             if(tokenStart >= tokenEnd) {    
  2192.                 /*     
  2193.                 No selection range, or selection range is screwed up (i.e. reversed). 
  2194.                 Note: The TE32K routines are always checking for reversed (**tH).selStart, 
  2195.                 (**tH).selEnd. I don't know of any cases where this happens, but I tread 
  2196.                 softly.
  2197.                 */
  2198.                 tokenEnd=tokenStart;
  2199.                 s=(unsigned char *) *(**tH).hText;
  2200.                 teLength = (**tH).teLength;
  2201.                 for(;tokenStart>0 && *(s+tokenStart-1)!='\n' && *(s+tokenStart-1)!='\r';tokenStart--) ;
  2202.                 for(;tokenEnd<teLength && *(s+tokenEnd)!='\n' && *(s+tokenEnd)!='\r';tokenEnd++) ;
  2203.                 tokenEnd++;
  2204.                 tokenStart = (tokenStart<0)? 0 : tokenStart;
  2205.                 if(tokenEnd>teLength) {
  2206.                     tokenEnd=teLength;
  2207.                     TE32KSetSelect(tokenEnd,tokenEnd,tH);
  2208.                 } else
  2209.                     TE32KSetSelect(tokenEnd-1,tokenEnd-1,tH);
  2210.                 commandLen = tokenEnd - tokenStart;
  2211.             } else
  2212.                 fCommandIsSelection=true;
  2213.             if(commandLen<255) {
  2214.                 BlockMove(*((**tH).hText) + tokenStart, gCommandLine,tokenEnd - tokenStart);
  2215.                 *(gCommandLine+commandLen) = '\0';
  2216.             } else 
  2217.                 commandLen = 0;
  2218.             HUnlock((**tH).hText);
  2219.         } 
  2220.         if(!fCommandIsSelection) {
  2221.             /* 
  2222.                 There is not need to update marks during normal typing as the undoStart and undoEnd
  2223.                 range provide an adequate record of how the buffer (hText) has changed. Two case
  2224.                 where updating are necessary are flagged here:
  2225.                     1. When auto-indenting and spaces follow the cursor
  2226.                     2. A selection range made by shift-arrow key combinations is deleted, after 
  2227.                         some previous typing.
  2228.                 Number 2 is too complex, so lets just update marks whenever a shifted character is 
  2229.                 typed. This catches all shift-arrow combinations. Updating with every new sentence
  2230.                 is not an important penalty.
  2231.             */
  2232.             if(ch==RETURN && (**tH).autoIndent 
  2233.                     && ((DocumentPeek)wind)->fNeedtoUpdateMarks
  2234.                     && ((*(**tH).hText + (**tH).selEnd)==' ' || (*(**tH).hText + (**tH).selEnd)==TAB)) {
  2235.                 UpdateMarks((DocumentPeek)wind,(**tH).undoStart,(**tH).undoEnd,(**tH).undoStart-(**tH).undoEnd,(**tH).teLength);
  2236.             } else if(((DocumentPeek)wind)->fNeedtoUpdateMarks &&
  2237.                 (ch==LEFTARROW || ch==RIGHTARROW || ch==UPARROW || ch==DOWNARROW)) {
  2238.                 selStart = (**tH).undoStart;
  2239.                 selEnd = (**tH).undoEnd;
  2240.                 if(selEnd > selStart)
  2241.                     delta = selEnd - selStart;
  2242.                 else 
  2243.                     delta=0;
  2244.                 if((**tH).undoBuf)
  2245.                     delta -= GetHandleSize((**tH).undoBuf);
  2246.                 /*
  2247.                     This is the second use of (**tH).undoDelta for input. The other is in 
  2248.                     ContentClick, which is the other way of moving the insertion point.
  2249.                 */
  2250.                 delta -= (**tH).undoDelta;
  2251.                 (**tH).undoDelta = delta;
  2252.                 if(selEnd > selStart)
  2253.                     selEnd-=delta;
  2254.                 UpdateMarks((DocumentPeek)wind,selStart,selEnd,delta,(**tH).teLength);
  2255.             }
  2256.                 
  2257.             result = TE32KKey(ch,tH,theEvent->modifiers);
  2258.             
  2259.             ((DocumentPeek)wind)->fNeedtoUpdateMarks |= result;
  2260.             ((DocumentPeek)wind)->fNeedtoSave |= result;
  2261.                     
  2262.             /* SynchScrollBars */
  2263.             AdjustScrollBars(wind);
  2264.             TE32KSelView(tH);
  2265.             SetScrollBarValues(wind);
  2266.             ((DocumentPeek)wind)->fHaveSelection = SetSelectionFlag(tH);
  2267.         }
  2268.         if(commandLen)
  2269.             DoCommandLine(wind);
  2270.     }
  2271. }
  2272.  
  2273. void textWriteOnlyDoKeyDown(WindowPtr wind,EventRecord *theEvent)
  2274. {
  2275.     unsigned ch;
  2276.     TE32KHandle tH;
  2277.     
  2278.     if(tH=(TE32KHandle)((DocumentPeek)wind)->docData) {
  2279.         ch=theEvent->message&charCodeMask;
  2280.  
  2281.         if(ch==LEFTARROW || ch==RIGHTARROW || ch==UPARROW || ch==DOWNARROW) {
  2282.             
  2283.             TE32KKey(ch,tH,theEvent->modifiers);
  2284.  
  2285.             /* SynchScrollBars */
  2286.             AdjustScrollBars(wind);
  2287.             TE32KSelView(tH);
  2288.             SetScrollBarValues(wind);
  2289.             ((DocumentPeek)wind)->fHaveSelection = SetSelectionFlag(tH);
  2290.  
  2291.         } else 
  2292.             doMessage(18);
  2293.     }
  2294. }
  2295.  
  2296. pascal void MyClicker(void)
  2297. {
  2298.     short        lineHeight;
  2299.     Rect        viewRect;
  2300.     Point        mousePoint;
  2301.     RgnHandle    saveClip;
  2302.     long        hDelta,vDelta;
  2303.  
  2304.     if (ClickedTE32KH) {
  2305.         LongRectToRect(&((**ClickedTE32KH).viewRect),&viewRect);
  2306.         lineHeight = (**ClickedTE32KH).lineHeight;
  2307.     
  2308.         hDelta = 0L;
  2309.         vDelta = 0L;
  2310.         
  2311.         GetMouse(&mousePoint);
  2312.         
  2313.         if (!PtInRect(mousePoint,&viewRect)) {
  2314.             if (mousePoint.v > viewRect.bottom && (**ClickedTE32KH).viewRect.bottom < (**ClickedTE32KH).destRect.top + (long) lineHeight * (**ClickedTE32KH).nLines)
  2315.                 vDelta = -lineHeight;
  2316.             
  2317.             else if (mousePoint.v < viewRect.top && (**ClickedTE32KH).viewRect.top > (**ClickedTE32KH).destRect.top)
  2318.                 vDelta = lineHeight;
  2319.             
  2320.             
  2321.             if (mousePoint.h > viewRect.right && (**ClickedTE32KH).viewRect.right < (**ClickedTE32KH).destRect.right)
  2322.                 hDelta = -lineHeight;
  2323.             
  2324.             else if (mousePoint.h<viewRect.left && (**ClickedTE32KH).viewRect.left > (**ClickedTE32KH).destRect.left)
  2325.                 hDelta = lineHeight;
  2326.         }
  2327.         
  2328.         if (hDelta || vDelta) {
  2329.             saveClip = NewRgn();
  2330.             GetClip(saveClip);
  2331.             viewRect = (*((**ClickedTE32KH).inPort)).portRect;
  2332.             ClipRect(&viewRect);
  2333.             
  2334.             TE32KScroll(hDelta,vDelta,ClickedTE32KH);
  2335.             AdjustScrollBars((**ClickedTE32KH).inPort);
  2336.             SetScrollBarValues((**ClickedTE32KH).inPort);
  2337.             
  2338.             SetClip(saveClip);
  2339.             DisposeRgn(saveClip);
  2340.         }
  2341.     }
  2342. }
  2343.  
  2344. void AddText(WindowPtr wind,Ptr text, long len)
  2345. {
  2346.     TE32KHandle tH;
  2347.     
  2348.     if(tH=(TE32KHandle)((DocumentPeek)wind)->docData) {
  2349.         TE32KInsert(text,len,tH);
  2350.         ((DocumentPeek)wind)->fNeedtoUpdateMarks = ((DocumentPeek)wind)->fNeedtoSave = true;
  2351.         /* SynchScrollBars */
  2352.         TE32KSelView(tH);
  2353.         AdjustScrollBars(wind);
  2354.         SetScrollBarValues(wind);
  2355.     }
  2356. }
  2357.  
  2358. Boolean SetTERect(WindowPtr wind)
  2359. {
  2360.     Rect r;
  2361.     TE32KHandle tH;
  2362.     
  2363.     if(((DocumentPeek)wind)->docData) {
  2364.         tH = (TE32KHandle)((DocumentPeek)wind)->docData;
  2365.         GetContentRect(wind,&r);
  2366.         RectToLongRect(&r,&(**tH).viewRect);
  2367.         (**tH).viewRect.bottom=(**tH).viewRect.top+((r.bottom-r.top)/(**tH).lineHeight)*(**tH).lineHeight;
  2368.         if((**tH).crOnly)
  2369.             (**tH).destRect.right=(**tH).destRect.left+8192;
  2370.         else if((**tH).wrapToLength) {
  2371.             (**tH).destRect.right=(**tH).destRect.left+(**tH).maxLineWidth*(**tH).theCharWidths['M'];
  2372.         } else {
  2373.             (**tH).destRect.right=(**tH).viewRect.right;
  2374.             (**tH).destRect.left=(**tH).viewRect.left;
  2375.         }
  2376.         return !(**tH).crOnly;
  2377.     }
  2378.     return false;
  2379. }
  2380.  
  2381. void textDoGrow(WindowPtr wind,EventRecord *event)
  2382. {    
  2383.     Rect r;
  2384.     TE32KHandle tH;
  2385.     
  2386.     if(doGrow(wind,event)) {
  2387.         SizeScrollBars(wind);
  2388.         if(SetTERect(wind)) {
  2389.             TE32KCalText(tH=(TE32KHandle)((DocumentPeek)wind)->docData);
  2390.             TE32KSetSelect((**tH).selStart,(**tH).selEnd,tH);
  2391.         }
  2392.         AdjustScrollBars(wind);
  2393.         SetScrollBarValues(wind);
  2394.         GetContentRect(wind,&r);
  2395.         InvalRect(&r);
  2396.         EraseRect(&r);
  2397.     }
  2398. }
  2399.  
  2400. void textDoZoom(WindowPtr wind,short partCode)
  2401. {
  2402.     TE32KHandle tH;
  2403.     Rect r;
  2404.     
  2405.     scrollDoZoom(wind,partCode);
  2406.     if(SetTERect(wind)) {    /* If wordwrapping, CalText. */
  2407.         TE32KCalText(tH=(TE32KHandle)((DocumentPeek)wind)->docData);
  2408.         TE32KSetSelect((**tH).selStart,(**tH).selEnd,tH);
  2409.         AdjustScrollBars(wind);
  2410.         SetScrollBarValues(wind);
  2411.     }
  2412.     GetContentRect(wind,&r);
  2413.     InvalRect(&r);
  2414.     EraseRect(&r);
  2415. }
  2416.  
  2417. void textDoContent(WindowPtr wind,EventRecord *event)
  2418. {
  2419.     Rect contents;
  2420.     Boolean shiftKeyDown;
  2421.     TE32KHandle tH;
  2422.     long selStart,selEnd,delta;
  2423.     
  2424.     FocusOnWindow(wind);
  2425.     GlobalToLocal(&event->where);
  2426.     (*((DocumentPeek)wind)->getContentRect)(wind,&contents);
  2427.     if(PtInRect(event->where,&contents)) {
  2428.         shiftKeyDown =((event->modifiers & shiftKey) != 0);
  2429.         /*
  2430.             This is the first use of (**tH).undoDelta as input. UndoDelta
  2431.             keeps a record of previous UpdateMarks. Obviously, one can click 
  2432.             many times and there be no change in the undoBuffer and UpdateMarks 
  2433.             based on the undoBuffer values shouldn't be redone.
  2434.             
  2435.             The other use is for arrow key cursor movement.
  2436.         */
  2437.         if(tH=(TE32KHandle)((DocumentPeek)wind)->docData) {
  2438.             if(((DocumentPeek)wind)->fNeedtoUpdateMarks) {
  2439.                 selStart = (**tH).undoStart;
  2440.                 selEnd = (**tH).undoEnd;
  2441.                 if(selEnd > selStart)
  2442.                     delta = selEnd - selStart;
  2443.                 else
  2444.                     delta = 0;
  2445.                 if((**tH).undoBuf)
  2446.                     delta -= GetHandleSize((**tH).undoBuf);
  2447.                 delta -= (**tH).undoDelta;
  2448.                 (**tH).undoDelta = delta;
  2449.                 if(selEnd > selStart)
  2450.                     selEnd-=delta;
  2451.                 UpdateMarks((DocumentPeek)wind,selStart,selEnd,delta,(**tH).teLength);
  2452.             }
  2453.             
  2454.             TE32KClick(event->where,shiftKeyDown,tH);
  2455.             
  2456.             ((DocumentPeek)wind)->fHaveSelection = SetSelectionFlag(tH);
  2457.         }
  2458.     } else
  2459.         ScrollClick(wind,event);
  2460. }
  2461.  
  2462. RectLocalToGlobal(Rect *r)
  2463. {
  2464.     Point pt;
  2465.     
  2466.     pt.h=r->left;
  2467.     pt.v=r->top;
  2468.     LocalToGlobal(&pt);
  2469.     r->left=pt.h;
  2470.     r->top=pt.v;
  2471.  
  2472.     pt.h=r->right;
  2473.     pt.v=r->bottom;
  2474.     LocalToGlobal(&pt);
  2475.     r->right=pt.h;
  2476.     r->bottom=pt.v;
  2477. }
  2478.  
  2479. Boolean inStdState(WindowPtr wind,Rect *r)
  2480. {
  2481.     Handle h;
  2482.     WStateData *ws;
  2483.     Boolean ret;
  2484.     GrafPtr oldPort;
  2485.     
  2486.     if(!((WindowPeek)wind)->spareFlag)
  2487.         return false;
  2488.     h=((WindowPeek)wind)->dataHandle;
  2489.     if(!h)
  2490.         return false;
  2491.     HLock(h);
  2492.     ws = (WStateData *)(*h);
  2493.     *r=wind->portRect;
  2494.     GetPort(&oldPort);
  2495.     SetPort(wind);
  2496.     RectLocalToGlobal(r);
  2497.     SetPort(oldPort);
  2498.     ret=EqualRect(r,&ws->stdState);
  2499.     HUnlock(h);
  2500.     return ret;
  2501. }
  2502.  
  2503. Boolean textMakeWindow(WindowPtr wind)
  2504. {
  2505.     Rect r;
  2506.     short hasGoAway;
  2507.     char *title;
  2508.     
  2509.     title=((DocumentPeek)wind)->fileSpecs.name;
  2510.  
  2511.     SetRect(&r,DragBoundsRect.left+5+25*NumWindows,
  2512.                         DragBoundsRect.top+25+25*NumWindows,
  2513.                         DragBoundsRect.right-40,
  2514.                         DragBoundsRect.bottom);
  2515.     if(!((r.right-r.left)%2)) r.right--;
  2516.     if(!((r.bottom-r.top)%2)) r.bottom--;
  2517.     
  2518.     /*     If we are supposed to be using a worksheet and there isn't one yet, 
  2519.         then this is the worksheet. */
  2520.         
  2521.     hasGoAway=(gUseWorksheet)? gPlainTextWSDoc!=0 : 1;
  2522.  
  2523.     wind=NewWindow((Ptr)wind,&r,"",false,zoomDocProc,gTextWindowPosition,hasGoAway,0);
  2524.     gTextWindowPosition=(WindowPtr)-1;
  2525.     
  2526.     ((DocumentPeek)wind)->fDocWindow=true;
  2527.     ((WindowPeek)wind)->windowKind = (hasGoAway)? 9:13;
  2528.     NumWindows++;
  2529.     if(*title) {
  2530.         SetDocWindowTitle(wind,title);
  2531.     }
  2532.     return true;
  2533. }
  2534.  
  2535. Boolean textInitDoc(WindowPtr wind)
  2536. {
  2537.     DocumentPeek doc;
  2538.     LongRect view,dest;
  2539.     TE32KHandle tH;
  2540.  
  2541.     doc = (DocumentPeek)wind;
  2542.     
  2543.     SetRect(&doc->limitRect,100,100,1000,1000);
  2544.     
  2545.     if(!(doc->fPrintRecord = (THPrint)NewHandle(sizeof(TPrint))))
  2546.         return false;
  2547.     PrOpen();
  2548.     PrintDefault(doc->fPrintRecord);
  2549.     PrClose();
  2550.  
  2551.     SetPort(wind);
  2552.     TextFont(monaco);
  2553.     TextSize(9);
  2554.     RectToLongRect(&wind->portRect,&dest);
  2555.     view=dest;
  2556.     dest.right=2000;
  2557.     dest.bottom=2000;
  2558.     dest.left+=4;
  2559.     dest.top+=4;
  2560.     tH=TE32KNew(&dest,&view);
  2561.     if(tH==NIL) {
  2562.         DisposeWindow(wind);
  2563.         doc->docData=NIL;
  2564.         doc->fDocWindow=false;
  2565.         InitCursor();
  2566.         doMessage(5);    
  2567.         return false;
  2568.     }
  2569.     (**tH).crOnly=false;
  2570.     doc->docData=(Handle)tH;
  2571.         
  2572.     if(!InitScrollDoc(wind))
  2573.         return false;
  2574.         
  2575.     SetTERect(wind);
  2576.  
  2577.     TE32KAutoView(true,tH);
  2578.         
  2579.     DrawControls(wind);
  2580.     DrawGrowIcon(wind);
  2581.     return true;
  2582. }
  2583.  
  2584. unsigned long GetModDate(FSSpec *specs)
  2585. {
  2586.     HFileParam pB;
  2587.     
  2588.     memset(&pB,0,sizeof(HFileParam));
  2589.     pB.ioCompletion=0;
  2590.     pB.ioNamePtr=specs->name;
  2591.     pB.ioVRefNum=specs->vRefNum;
  2592.     pB.ioFDirIndex=0;
  2593.     pB.ioDirID=specs->parID;
  2594.         
  2595.     PBHGetFInfoSync((HParmBlkPtr)&pB);
  2596.     
  2597.     return pB.ioFlMdDat;
  2598. }
  2599.  
  2600. void SetModDate(FSSpec *specs, unsigned long modDate)
  2601. {
  2602.     OSErr err;
  2603.     HFileParam pB;
  2604.     
  2605.     if(modDate) {
  2606.         memset(&pB,0,sizeof(HFileParam));
  2607.         pB.ioCompletion=0;
  2608.         pB.ioNamePtr=specs->name;
  2609.         pB.ioVRefNum=specs->vRefNum;
  2610.         pB.ioFDirIndex=0;
  2611.         pB.ioDirID=specs->parID;
  2612.         
  2613.         err=PBHGetFInfoSync((HParmBlkPtr)&pB);
  2614.         
  2615.         pB.ioFlMdDat=modDate;
  2616.         pB.ioDirID=specs->parID;
  2617.  
  2618.         err=PBHSetFInfoSync((HParmBlkPtr)&pB);
  2619.     }
  2620. }
  2621.  
  2622. int ReadTextDocResourceFork(WindowPtr wind)
  2623. {
  2624.     Handle res;
  2625.     short err,refNum,nMarks;
  2626.  
  2627.     /*    
  2628.         Text files have two resources. Both follow formats used by MPW.
  2629.     
  2630.         MPSR 1005 is obligatory and encodes all format information, window
  2631.         size, scroll bar position and selection range.
  2632.         
  2633.         MPSR 1007 encodes marks.
  2634.     */
  2635.     
  2636.     refNum=((DocumentPeek)wind)->resourcePathRefNum;
  2637.     if(!refNum)
  2638.         return false;
  2639.         
  2640.     UseResFile(refNum);
  2641.     res=Get1Resource('MPSR',1005);
  2642.     
  2643.     ((DocumentPeek)wind)->windowState=res;
  2644.     
  2645.     /*     Retrieve the file's modified date so that it can be retained should 
  2646.         file's resources be changed but the file not dirtied.  Changes in
  2647.         marks, scroll position, window size, and selection range do not
  2648.         dirty a text file. Neither does show invisibles, or any font changes. */
  2649.     
  2650.     if(res) 
  2651.         ((MPSRPtr)*res)->modifiedDate=GetModDate(&((DocumentPeek)wind)->fileSpecs);
  2652.  
  2653.     /* Now see if there are already marks for this file. */
  2654.     
  2655.     res=Get1Resource('MPSR',1007);
  2656.     ((DocumentPeek)wind)->marks=(ResError()==noErr)? res:0;
  2657.     if(res=((DocumentPeek)wind)->marks) {
  2658.         nMarks = *((short *)*res);
  2659.         if(nMarks == 0)    {    /*     There are no marks. This can only 
  2660.                                         happen if a foreign file, i.e. MPW,
  2661.                                         has opened this file and left an
  2662.                                         MPSR 1007 resource that should have
  2663.                                         been removed. */
  2664.             RmveResource(res);
  2665.             err=ResError();
  2666.             DisposeHandle(res);
  2667.             ((DocumentPeek)wind)->marks=0;
  2668.         }
  2669.     }
  2670.     
  2671.     return true;
  2672. }
  2673.  
  2674. void readOnlyAdjustDocMenus(WindowPtr wind)
  2675. {
  2676.     
  2677.     /* File Menu */
  2678.     EnableItem(FileMenu,iClose);
  2679.     
  2680.     DisableItem(FileMenu,iSave);
  2681.     EnableItem(FileMenu,iSaveAs);
  2682.     EnableItem(FileMenu,iSaveACopy);
  2683.     DisableItem(FileMenu,iRevert);
  2684.     EnableItem(FileMenu,iPageSetup);
  2685.     EnableItem(FileMenu,iPrint);
  2686.         
  2687.     /* Edit Menu */
  2688.     DisableItem(EditMenu,iUndo);
  2689.     DisableItem(EditMenu,iCut);
  2690.     SetMenuAbility(EditMenu,iCopy,((DocumentPeek)wind)->fHaveSelection);
  2691.     DisableItem(EditMenu,iPaste);    
  2692.     DisableItem(EditMenu,iClear);
  2693.     EnableItem(EditMenu,iSelectAll);
  2694.     EnableItem(EditMenu,iShowClipboard);
  2695.     EnableItem(EditMenu,iFormat);
  2696.     
  2697.     DisableItem(EditMenu,iAlign);
  2698.     DisableItem(EditMenu,iShiftRight);
  2699.     DisableItem(EditMenu,iShiftLeft);
  2700.     
  2701.     EnableItem(FileMenu,0);
  2702.     EnableItem(EditMenu,0);
  2703.     EnableItem(FindMenu,0);
  2704.     EnableItem(MarkMenu,0);
  2705.     EnableItem(WindowMenu,0);
  2706.     DisableItem(ConvertMenu,0);
  2707. }
  2708.  
  2709. Boolean textOpenDocFile(WindowPtr wind)
  2710. {
  2711.     DocumentPeek doc;
  2712.     
  2713.     if(openDocFile(wind)) {
  2714.         doc = (DocumentPeek)wind;
  2715.         if(doc->fReadOnly) {
  2716.             doc->doKeyDown=textWriteOnlyDoKeyDown;
  2717.             doc->writeDocFile=nullIntMethod;
  2718.             doc->adjustDocMenus=readOnlyAdjustDocMenus;
  2719.         } else {
  2720.             doc->doKeyDown=textDoKeyDown;
  2721.             doc->writeDocFile=textWriteDocFile;
  2722.             doc->adjustDocMenus=textAdjustDocMenus;
  2723.         }
  2724.         return true;
  2725.     }
  2726.     return false;
  2727. }
  2728.  
  2729. int textReadDocFile(WindowPtr wind)
  2730. {
  2731.     DocumentPeek doc;
  2732.     short refNum,fontNum;
  2733.     long len,selEnd,selStart;
  2734.     OSErr err;
  2735.     Handle theText;
  2736.     TE32KHandle tH;    
  2737.     
  2738.     doc = (DocumentPeek)wind;
  2739.     
  2740.     if((doc->fDocWindow)&&(doc->docData)) {
  2741.         refNum=doc->dataPathRefNum;
  2742.         err = GetEOF(refNum,&len);
  2743.  
  2744.         theText=NewHandle(len);
  2745.         if(MemError() || StripAddress(theText)==nil) {
  2746.             doMessage(1);
  2747.             return false;
  2748.         }
  2749.         
  2750.         HLock(theText);
  2751.         err = SetFPos(refNum,fsFromStart,0);
  2752.         err = FSRead(refNum,&len,(Ptr)*theText);
  2753.         HUnlock(theText);
  2754.         if(err == noErr) {
  2755.             tH = (TE32KHandle)doc->docData;
  2756.             if((**tH).hText)
  2757.                 DisposeHandle((**tH).hText);
  2758.             (**tH).hText=theText;
  2759.             (**tH).teLength=len;
  2760.             (**tH).selStart=len;
  2761.             (**tH).selEnd=len;
  2762.             
  2763.             ReadTextDocResourceFork(wind);
  2764.                         
  2765.             if(doc->windowState) {
  2766.                 HLock(doc->windowState);
  2767.                 (**tH).showInvisibles=((MPSRPtr)*doc->windowState)->showInvisibles;
  2768.                 (**tH).crOnly = !(((MPSRPtr)*doc->windowState)->wordWrap&2);
  2769.                 (**tH).wrapToLength = ((MPSRPtr)*doc->windowState)->wordWrap&4;
  2770.                 (**tH).autoIndent = ((MPSRPtr)*doc->windowState)->wordWrap&1;
  2771.                 (**tH).tabChars=((MPSRPtr)*doc->windowState)->tabWidth;
  2772.                 GetFNum(c2pstr(((MPSRPtr)*doc->windowState)->fontName),&fontNum);
  2773.                 p2cstr(((MPSRPtr)*doc->windowState)->fontName);
  2774.                 TE32KSetFontStuff(fontNum,(**tH).txFace,(**tH).txMode,((MPSRPtr)*doc->windowState)->fontSize,tH);
  2775.                 HUnlock(doc->windowState);
  2776.             }
  2777.         
  2778.             SetTERect(wind);
  2779.             TE32KCalText(tH);
  2780.  
  2781.             if(doc->windowState) {
  2782.                 selStart=((MPSRPtr)*doc->windowState)->vScrollValue;
  2783.                 selEnd=indexToLine(selStart,tH);
  2784.                 ScrollContents(wind,(short)0,(short)-selEnd);
  2785.                 
  2786.                 selStart=((MPSRPtr)*doc->windowState)->selStart;
  2787.                 selEnd=((MPSRPtr)*doc->windowState)->selEnd;
  2788.                 if(selEnd>selStart)
  2789.                     doc->fHaveSelection=true;
  2790.                 TE32KSetSelect(selStart,selEnd,tH);
  2791.             }
  2792.             AdjustScrollBars(wind);
  2793.             SetScrollBarValues(wind);
  2794.             
  2795.             return true;
  2796.         } else {
  2797.             DisposeHandle(theText);
  2798.             return false;
  2799.         }
  2800.     }
  2801.     return false;
  2802. }
  2803.  
  2804. int textWriteDocResourceFork(WindowPtr wind)
  2805. {
  2806.     DocumentPeek doc;
  2807.     short val,nMarks;
  2808.     Handle h,res;
  2809.     Rect r;
  2810.     WStateData *ws;
  2811.     MPSRPtr state;
  2812.     TE32KHandle tH;
  2813.     Str255 fontName;
  2814.     
  2815.     doc = (DocumentPeek) wind;
  2816.     if(!doc->resourcePathRefNum)
  2817.         return 0;
  2818.         
  2819.     UseResFile(doc->resourcePathRefNum);
  2820.     
  2821.     res=doc->windowState;
  2822.     if(!doc->windowState) {
  2823.         /* Resource is missing. Make one. */
  2824.         res=NewHandle(sizeof(MPSRWindowResource));
  2825.         if(!res)
  2826.             return 0;    /* Not enough memory */
  2827.         HLock(res);
  2828.         state=(MPSRPtr)*res;
  2829.         state->modifiedDate = GetModDate(&doc->fileSpecs);
  2830.     }
  2831.     
  2832.     HLock(res);
  2833.     state=(MPSRPtr)*res;
  2834.         
  2835.     if(inStdState((WindowPtr)doc,&r)) {
  2836.         h=((WindowPeek)doc)->dataHandle;
  2837.         HLock(h);
  2838.         ws = (WStateData *)(*h);
  2839.         state->userState=ws->stdState;
  2840.         state->stdState=ws->userState;
  2841.         HUnlock(h);
  2842.     } else {
  2843.         state->userState=r;
  2844.         state->stdState=r;
  2845.     }
  2846.     
  2847.     tH=(TE32KHandle)doc->docData;
  2848.     state->selStart=(**tH).selStart;
  2849.     state->selEnd=(**tH).selEnd;
  2850.     val=GetCtlValue(doc->vScroll);
  2851.     state->vScrollValue = (**tH).lineStarts[val];
  2852.  
  2853.     state->showInvisibles=(**tH).showInvisibles;
  2854.     state->wordWrap=(((**tH).autoIndent)?1:0) | (((**tH).crOnly)?0:2) |(((**tH).wrapToLength)?4:0);
  2855.     state->tabWidth=(**tH).tabChars;
  2856.     state->fontWidth=(**tH).theCharWidths[' '];
  2857.     state->fontSize=(**tH).txSize;
  2858.     
  2859.     GetFontName((**tH).txFont,fontName);
  2860.  
  2861.     strcpy(state->fontName,p2cstr(fontName));
  2862.  
  2863.     HUnlock(res);
  2864.         
  2865.     if(!doc->windowState) {
  2866.         doc->windowState=res;
  2867.         AddResource(res,'MPSR',1005,"");
  2868.     } else
  2869.         ChangedResource(doc->windowState);
  2870.         
  2871.     WriteResource(doc->windowState);
  2872.     
  2873.     if(doc->marks) {
  2874.         nMarks = *(short *)*doc->marks ;
  2875.         if(nMarks) {
  2876.             if(HomeResFile(doc->marks)!=-1) {
  2877.                 ChangedResource(doc->marks);
  2878.                 WriteResource(doc->marks);
  2879.             } else  {
  2880.                 AddResource(doc->marks,'MPSR',1007,"");
  2881.                 WriteResource(doc->marks);
  2882.             }
  2883.         } else {
  2884.             if(res) {
  2885.                 RmveResource(res);
  2886.                 DisposeHandle(res);
  2887.             }
  2888.         }
  2889.     }        
  2890. }
  2891.  
  2892. int textWriteDocFile(WindowPtr wind)
  2893. {
  2894.     DocumentPeek doc;
  2895.     short refNum;
  2896.     OSErr err;
  2897.     long len;
  2898.     Handle theText;
  2899.     TE32KHandle tH;
  2900.     unsigned long modDate;
  2901.     
  2902.     doc = (DocumentPeek)wind;
  2903.     
  2904.     if((doc->fDocWindow)&&(doc->docData)) {
  2905.         textWriteDocResourceFork(wind);
  2906.         refNum=doc->dataPathRefNum;
  2907.         tH = (TE32KHandle)doc->docData;
  2908.         len = (**tH).teLength;
  2909.         theText = (**tH).hText;
  2910.         HLock(theText);
  2911.         err = SetFPos(refNum,fsFromStart,0);
  2912.         err |= FSWrite(refNum,&len,*theText);
  2913.         HUnlock(theText);
  2914.         err |= SetEOF(refNum,len);
  2915.         err |= FlushVol("",doc->fileSpecs.vRefNum);
  2916.         if(err==noErr) {
  2917.             if(doc->windowState) {
  2918.                 GetDateTime(&modDate);
  2919.                 ((MPSRPtr)*doc->windowState)->modifiedDate = modDate;
  2920.             }
  2921.             return true;
  2922.         }
  2923.     }
  2924.     return false;
  2925. }
  2926.  
  2927. void textAdjustDocMenus(WindowPtr wind)
  2928. {
  2929.     DocumentPeek doc;
  2930.     long selStart,selEnd,delta=0;
  2931.     TE32KHandle tH;
  2932.  
  2933.     doc=(DocumentPeek)wind;
  2934.     
  2935.     if(doc->fNeedtoUpdateMarks && (tH=(TE32KHandle)doc->docData)) {
  2936.         selStart = (**tH).undoStart;
  2937.         selEnd = (**tH).undoEnd;
  2938.         if(selEnd > selStart)
  2939.             delta = selEnd - selStart;
  2940.         if((**tH).undoBuf) 
  2941.             delta -= GetHandleSize((**tH).undoBuf);
  2942.         delta -= (**tH).undoDelta;
  2943.         (**tH).undoDelta = delta;
  2944.         if(selEnd > selStart)
  2945.             selEnd-=delta;
  2946.         UpdateMarks((DocumentPeek)wind,selStart,selEnd,delta,(**tH).teLength);
  2947.     }
  2948.     
  2949.     /* File Menu */
  2950.     SetMenuAbility(FileMenu,iClose,((WindowPeek)doc)->windowKind!=13);
  2951.         /* Can't close Worksheet */
  2952.     SetMenuAbility(FileMenu,iSave,doc->fNeedtoSave);
  2953.     SetMenuAbility(FileMenu,iSaveAs,((WindowPeek)doc)->windowKind!=13);
  2954.     EnableItem(FileMenu,iSaveACopy);
  2955.     SetMenuAbility(FileMenu,iRevert,doc->fNeedtoSave);
  2956.     EnableItem(FileMenu,iPageSetup);
  2957.     EnableItem(FileMenu,iPrint);
  2958.         
  2959.     /* Edit Menu */
  2960.     SetMenuAbility(EditMenu,iUndo,doc->fNeedtoSave);
  2961.     SetMenuAbility(EditMenu,iCut,doc->fHaveSelection);
  2962.     SetMenuAbility(EditMenu,iCopy,doc->fHaveSelection);
  2963.     EnableItem(EditMenu,iPaste);    
  2964.     SetMenuAbility(EditMenu,iClear,doc->fHaveSelection);
  2965.     EnableItem(EditMenu,iSelectAll);
  2966.  
  2967.     EnableItem(EditMenu,iFormat);
  2968.     
  2969.     EnableItem(EditMenu,iAlign);
  2970.     EnableItem(EditMenu,iShiftRight);
  2971.     EnableItem(EditMenu,iShiftLeft);
  2972.  
  2973.     /* Find Menu */
  2974.     EnableItem(FindMenu,iFind);
  2975.     SetMenuAbility(FindMenu,iFindSame,*gFindBuffer);
  2976.     SetMenuAbility(FindMenu,iFindSelection,doc->fHaveSelection>0);
  2977.     EnableItem(FindMenu,iDisplaySelection);    
  2978.     EnableItem(FindMenu,iReplace);
  2979.     SetMenuAbility(FindMenu,iReplaceSame,*gFindBuffer);
  2980.     
  2981.     EnableItem(FileMenu,0);
  2982.     EnableItem(EditMenu,0);
  2983.     EnableItem(FindMenu,0);
  2984.     EnableItem(MarkMenu,0);
  2985.     EnableItem(WindowMenu,0);
  2986.     EnableItem(ConvertMenu,0);
  2987. }
  2988.  
  2989. int forSearch(char *buf, char *end, char *what, int len)
  2990. {
  2991.     int i,offset;
  2992.     
  2993.     for(offset=0;buf<end;buf++,offset++) {
  2994.         if(tolower(*buf) == tolower(*what)) {
  2995.             for(i=1;i<len;i++) {
  2996.                 if(tolower(*(buf+i)) != tolower(*(what+i)))
  2997.                     goto NoMatch;
  2998.             }
  2999.             return offset;
  3000.         }
  3001. NoMatch:    ;
  3002.     }
  3003.     return -1;
  3004. }
  3005.  
  3006. int forCSSearch(char *buf, char *end, char *what, int len)
  3007. {
  3008.     int i,offset;
  3009.     
  3010.     for(offset=0;buf<end;buf++,offset++) {
  3011.         if(*buf == *what) {
  3012.             for(i=1;i<len;i++) {
  3013.                 if(*(buf+i) != *(what+i))
  3014.                     goto NoMatch;
  3015.             }
  3016.             return offset;
  3017.         }
  3018. NoMatch:    ;
  3019.     }
  3020.     return -1;
  3021. }
  3022.  
  3023. int revSearch(char *buf, char *start, char *what, int len)
  3024. {
  3025.     int i,offset;
  3026.     
  3027.     for(offset=-1;buf>=start;buf--,offset--) {
  3028.         if(toupper(*buf) == toupper(*what)) {
  3029.             for(i=1;i<len;i++) {
  3030.                 if(toupper(*(buf+i)) != toupper(*(what+i)))
  3031.                     goto NoMatch;
  3032.             }
  3033.             return offset;
  3034.         }
  3035. NoMatch:    ;
  3036.     }
  3037.     return 0;
  3038. }
  3039.  
  3040. int revCSSearch(char *buf, char *start, char *what, int len)
  3041. {
  3042.     int i,offset;
  3043.     
  3044.     for(offset=-1;buf>=start;buf--,offset--) {
  3045.         if(*buf == *what) {
  3046.             for(i=1;i<len;i++) {
  3047.                 if(*(buf+i) != *(what+i))
  3048.                     goto NoMatch;
  3049.             }
  3050.             return offset;
  3051.         }
  3052. NoMatch:    ;
  3053.     }
  3054.     return 0;
  3055. }
  3056.  
  3057. int RSearch(Handle h,int offset,const char *what,int len)
  3058. {
  3059.     int where,notFound;
  3060.     
  3061.     HLock(h);
  3062.     notFound = (gSearchMethod==1);
  3063.     do {
  3064.         where = (gCaseSensitive)? 
  3065.                     revCSSearch(*h+offset-1,*h,what,len) : 
  3066.                     revSearch(*h+offset-1,*h,what,len) ;
  3067.         offset+=where;
  3068.         if(where) {
  3069.             if(gSearchMethod==1) {        /* Whole word */
  3070.                 if(isalnum(*(*h+offset+len)) || (offset && isalnum(*(*h+offset-1)))) 
  3071.                     ;
  3072.                 else
  3073.                     notFound = 0;    /* Trip out */
  3074.             }
  3075.         } else
  3076.             notFound = 0;
  3077.     } while (notFound) ;
  3078.     HUnlock(h);
  3079.     return (where)? offset : -1;
  3080. }
  3081.  
  3082. char *matchLiteral(char *buf,char *lit,int *foundLen,int *litLen)
  3083. {
  3084.     char *p,*match;
  3085.     int len1=0,len2=0;
  3086.     Str255 searchStr;
  3087.     
  3088.     /* fill the search string */
  3089.     p=searchStr;
  3090.     while(*lit && *lit!='*' && *lit!='≈' && *lit!='?' && *lit!='[') {
  3091.         *p++ = *lit ++;
  3092.         len1++;
  3093.         len2++;
  3094.     }
  3095.     *p='\0';
  3096.     *foundLen+=len1;
  3097.     *litLen+=len2;
  3098.     if(gCaseSensitive) {
  3099.         match=strstr(buf,searchStr);
  3100.         buf+=len1;
  3101.     } else {
  3102.         for(p=searchStr;*p;p++)
  3103.             *p=toupper(*p);
  3104.         p=searchStr;
  3105.         while(*buf) {
  3106.             while(*buf && *p!=toupper(*buf)) buf++;
  3107.             if(*(match=buf)) {
  3108.                 p++;
  3109.                 buf++;
  3110.                 while(*p) {
  3111.                     if(*p!=toupper(*buf)) {
  3112.                         p=searchStr;
  3113.                         buf++;
  3114.                         match=0;
  3115.                         break;
  3116.                     }
  3117.                     p++;
  3118.                     buf++;
  3119.                 }
  3120.                 if(!*p)
  3121.                     break;
  3122.             }
  3123.         }
  3124.     }
  3125.     if(match) {
  3126.         len1=len2=0;
  3127.         if(matchExpressionRight(buf,lit+len2,&len1,&len2)) {
  3128.             *foundLen+=len1;
  3129.             *litLen+=len2;
  3130.             return match;
  3131.         }
  3132.     }
  3133.     return 0;
  3134. }
  3135.  
  3136. char *matchRange(char *buf,char *lit,int *foundLen,int *rangeLen)
  3137. {
  3138.     char *p,*match;
  3139.     int len1=0,len2=0,repeats=false;
  3140.     Str255 searchStr;
  3141.     
  3142.     /* fill the search string */
  3143.     p=searchStr;
  3144.     while(*lit && *lit!=']') {
  3145.         *p++ = *lit ++;
  3146.         len2++;
  3147.     }
  3148.     if(!*lit) {
  3149.         CommandLineError(0);
  3150.         return 0;
  3151.     }
  3152.     len2++;
  3153.     if(*(p-1)=='*') {
  3154.         repeats=true;
  3155.         p--;
  3156.     }
  3157.     *p='\0';
  3158.     
  3159.     if(match=strpbrk(buf,searchStr)) {
  3160.         len1=(repeats)?strspn(match,searchStr):1;
  3161.         *foundLen+=len1;
  3162.         len1=len2=0;
  3163.         if(matchExpressionRight(buf+len1,lit+len2,&len1,&len2)) {
  3164.             *foundLen+=len1;
  3165.             *rangeLen+=len2;
  3166.             return match;
  3167.         }
  3168.     }
  3169.     return 0;
  3170. }
  3171.  
  3172. char *matchExpressionRight(char *buf,char *exp,int *foundLen,int *expLen)
  3173. {
  3174.     char *anchor,*start,*match;
  3175.     Boolean doLeft=false;
  3176.     
  3177.     anchor=exp;
  3178.     start=buf;
  3179.     for(;;) {
  3180.         if(*anchor=='?') {
  3181.             start++;
  3182.             doLeft=true;
  3183.         } else if(*anchor=='*' || anchor=='≈') 
  3184.             doLeft=true;
  3185.         else
  3186.             break;
  3187.         anchor++;
  3188.     }
  3189.     if(!*anchor)
  3190.         match=start;
  3191.     else if(*anchor=='[') 
  3192.         match=matchRange(start,anchor+1,foundLen,expLen);
  3193.     else
  3194.         match=matchLiteral(start,anchor,foundLen,expLen);
  3195.     if(match && doLeft) {
  3196.         while(anchor>exp) {
  3197.             anchor--;
  3198.             if(*anchor=='?') {
  3199.                 match--;
  3200.                 (*foundLen)++;
  3201.                 (*expLen)++;
  3202.             } else if(*anchor=='*' || *anchor=='≈') {
  3203.                 while(match>buf && *match!='\n') {
  3204.                     match--;
  3205.                     (*foundLen)++;
  3206.                 }
  3207.                 if(*match=='\n') {
  3208.                     match++;
  3209.                     (*foundLen)--;
  3210.                 }
  3211.             }
  3212.             (*expLen)++;
  3213.         }
  3214.     }
  3215.     return match;
  3216. }
  3217.  
  3218. int ExpressionMatch(char *buf,char *end,char *exp,int *expLen)
  3219. {
  3220.     
  3221.     char storage,*found;
  3222.     int len1=0,len2=0;
  3223.     
  3224.     storage = *(end-1);
  3225.     *(end-1)='\0';
  3226.     found=matchExpressionRight(buf,exp,&len1,&len2);
  3227.     *expLen=len1;
  3228.     *(end-1)=storage;
  3229.     if(found)
  3230.         return found-buf+1;
  3231.     else
  3232.         return -1;
  3233. }
  3234.  
  3235. int ExpressionSearch(Handle h,int offset,const char *what,int *len)
  3236. {
  3237.     int where,hLen,foundLen;
  3238.     Str255 expressionString;
  3239.     
  3240.     BlockMove(what,expressionString,*len);
  3241.     *(expressionString+*len)='\0';
  3242.     hLen = GetHandleSize(h);
  3243.     HLock(h);
  3244.     where = ExpressionMatch(*h+offset+1,*h+hLen,expressionString,&foundLen);
  3245.     offset+=where;
  3246.     *len=foundLen;
  3247.     if(where && gSearchMethod==1) {
  3248.         if(isalnum(*(*h+offset+*len-1)) || (offset<hLen && isalnum(*(*h+offset+1)))) {
  3249.             HUnlock(h);
  3250.             return -1;
  3251.         }
  3252.     }    
  3253.     HUnlock(h);
  3254.     return (where)? offset : -1;
  3255. }
  3256.  
  3257. int FSearch(Handle h,int offset,const char *what,int len)
  3258. {
  3259.     int where,hLen;
  3260.     
  3261.     hLen = GetHandleSize(h);
  3262.     HLock(h);
  3263.     
  3264.     do {
  3265.         where = (gCaseSensitive)? 
  3266.                     forCSSearch(*h+offset,*h+hLen,what,len) : 
  3267.                     forSearch(*h+offset,*h+hLen,what,len) ;
  3268.         if(where>=0) {
  3269.             offset+=where;
  3270.             if(where && gSearchMethod==1) {
  3271.                 if(isalnum(*(*h+offset-1)) || 
  3272.                     ((offset+len)<hLen && isalnum(*(*h+offset+len)))) 
  3273.                         offset+=len;
  3274.                 else
  3275.                     where = -1; /* Trip out */
  3276.             } else 
  3277.                 where = -1;        /* Found string. Trip out. */
  3278.         } else /* where == -1 means string not found. Exit. */
  3279.             offset = -1;
  3280.     } while (where>=0) ;
  3281.     HUnlock(h);
  3282.     return offset;
  3283. }
  3284.  
  3285. Boolean findSearchString(WindowPtr wind, short direction)
  3286. {
  3287.     int where,end,lastLine,foundLength;
  3288.     TE32KHandle tH;
  3289.  
  3290.     if(tH=(TE32KHandle)((DocumentPeek)wind)->docData) {
  3291.         if(gSearchMethod==2) {    /* Selection expression */
  3292.             if(isdigit(*(gFindBuffer+1))) {
  3293.                 lastLine=(**tH).nLines-1;
  3294.                 /* Since nLines isn’t right if the last character is a return, check for that case.
  3295.                     (hint from TESample example. */
  3296.                 if ( *(*(**tH).hText + (**tH).teLength - 1) == '\n' )
  3297.                     lastLine++;
  3298.                 
  3299.                 *(gFindBuffer + *gFindBuffer + 1) = '\0';
  3300.                 where=atoi(gFindBuffer+1);
  3301.                 where=(where>lastLine)? lastLine : where ;
  3302.                 where=(where<=0)? 1 : where;
  3303.                 end = (**tH).lineStarts[where];
  3304.                 where = (**tH).lineStarts[where-1];
  3305.             } else {
  3306.                 foundLength=*gFindBuffer;
  3307.                 where=ExpressionSearch((**tH).hText,(**tH).selEnd,gFindBuffer+1,&foundLength);
  3308.                 if(where<0 && gWrapSearch) {    /* not found, try one more time, from start */
  3309.                     foundLength=*gFindBuffer;
  3310.                     where=ExpressionSearch((**tH).hText,0,gFindBuffer+1,&foundLength);
  3311.                     if(where==(**tH).selStart && foundLength==((**tH).selEnd-(**tH).selStart))
  3312.                         where=-1;
  3313.                 }
  3314.                 end = where + foundLength;
  3315.             }
  3316.         } else {
  3317.             if((direction)? !gSearchBackwards : gSearchBackwards)
  3318.                 where=RSearch((**tH).hText,(**tH).selStart,gFindBuffer+1,(long)*gFindBuffer);
  3319.             else
  3320.                 where=FSearch((**tH).hText,(**tH).selEnd,gFindBuffer+1,(long)*gFindBuffer);
  3321.             if(where<0 && gWrapSearch) {    /* not found, try one more time, from start */
  3322.                 if((direction)? !gSearchBackwards : gSearchBackwards)
  3323.                     where=RSearch((**tH).hText,(**tH).teLength,gFindBuffer+1,(long)*gFindBuffer);
  3324.                 else
  3325.                     where=FSearch((**tH).hText,0,gFindBuffer+1,(long)*gFindBuffer);
  3326.                 if(where==(**tH).selStart && *gFindBuffer==((**tH).selEnd-(**tH).selStart))
  3327.                     where=-1;
  3328.             }
  3329.             end = where + *gFindBuffer;
  3330.         }
  3331.         if(where>=0) {
  3332.             TE32KSetSelect(where,end,tH);
  3333.             TE32KSelView(tH);            
  3334.             AdjustScrollBars(wind);
  3335.             SetScrollBarValues(wind);
  3336.             ((DocumentPeek)wind)->fHaveSelection = 1;
  3337.             return true;
  3338.         }
  3339.         SysBeep(7);
  3340.     }
  3341.     return false;
  3342. }
  3343.  
  3344. pascal Boolean DialogStandardKeyDown(DialogPtr dialog, EventRecord *theEvent, short *itemHit)
  3345. {
  3346.     Rect box;
  3347.     Handle itemHand;
  3348.     short itemType;
  3349.     char key;
  3350.     
  3351.     if(theEvent->what==keyDown) {
  3352.         key=theEvent->message&charCodeMask;
  3353.         switch(key) {
  3354.             case 3: case 13:        /* Enter or CR */
  3355.                 GetDItem(dialog,1,&itemType,&itemHand,&box);
  3356.                 HiliteControl((ControlHandle)itemHand,1);
  3357.                 *itemHit=1;
  3358.                 return true;
  3359.             case 46:                /* Period */
  3360.                 if(theEvent->modifiers&0x100) {
  3361.             case 27:                /* Escape */
  3362.                     GetDItem(dialog,2,&itemType,&itemHand,&box);
  3363.                     HiliteControl((ControlHandle)itemHand,2);
  3364.                     *itemHit=2;
  3365.                     return true;
  3366.                 }
  3367.             default:
  3368.                 return false;
  3369.         }
  3370.     }
  3371.     return false;
  3372. }
  3373.  
  3374. Boolean doFindDialog(short which)
  3375. {
  3376.     DialogPtr findDialog;
  3377.     short itemHit;
  3378.     short itemType;
  3379.     Handle itemHand;
  3380.     int pau=false,result=false;
  3381.     Rect box;
  3382.     WindowPtr targetWindow;
  3383.     
  3384.     targetWindow=FrontLayer();
  3385.     findDialog=GetNewDialog(which,(Ptr)&DlogStor,(WindowPtr)(-1));
  3386.     /* Note: map Dialog is 137 */
  3387.     if(!findDialog) 
  3388.         FatalError();
  3389.  
  3390.     GetDItem(findDialog,11,&itemType,&itemHand,&box);
  3391.     SetDItem(findDialog,11,itemType,(Handle)doLine,&box);
  3392.     GetDItem(findDialog,12,&itemType,&itemHand,&box);
  3393.     SetDItem(findDialog,12,itemType,(Handle)doLine,&box);
  3394.     GetDItem(findDialog,13,&itemType,&itemHand,&box);
  3395.     SetDItem(findDialog,13,itemType,(Handle)doButton,&box);
  3396.     GetDItem(findDialog,4,&itemType,&itemHand,&box);
  3397.     SetIText(itemHand,gFindBuffer);
  3398.     SelIText(findDialog,4,0,32767);
  3399.     while(!pau) {
  3400.         /* Initialize the three radio buttons */
  3401.         GetDItem(findDialog,5,&itemType,&itemHand,&box);
  3402.         SetCtlValue((ControlHandle)itemHand,gSearchMethod==0);
  3403.         GetDItem(findDialog,6,&itemType,&itemHand,&box);
  3404.         SetCtlValue((ControlHandle)itemHand,gSearchMethod==1);
  3405.         GetDItem(findDialog,7,&itemType,&itemHand,&box);
  3406.         SetCtlValue((ControlHandle)itemHand,gSearchMethod==2);
  3407.         /* Do the check boxes */
  3408.         GetDItem(findDialog,8,&itemType,&itemHand,&box);
  3409.         SetCtlValue((ControlHandle)itemHand,gCaseSensitive);
  3410.         GetDItem(findDialog,9,&itemType,&itemHand,&box);
  3411.         SetCtlValue((ControlHandle)itemHand,gSearchBackwards);
  3412.         GetDItem(findDialog,10,&itemType,&itemHand,&box);
  3413.         SetCtlValue((ControlHandle)itemHand,gWrapSearch);
  3414.         
  3415.         ModalDialog(DialogStandardFilter,&itemHit);
  3416.  
  3417.         switch(itemHit) {
  3418.             case 1:
  3419.                 pau=true;
  3420.                 GetDItem(findDialog,4,&itemType,&itemHand,&box);
  3421.                 GetIText(itemHand,gFindBuffer);
  3422.                 result=true;;
  3423.                 break;
  3424.             case 2:
  3425.                 pau=true;
  3426.                 break;
  3427.             case 5:            /* Survey or Literal Radio Button */
  3428.                 gSearchMethod=0;
  3429.                 break;
  3430.             case 6:            /* Station or Entire Word */
  3431.                 gSearchMethod=1;
  3432.                 break;
  3433.             case 7:            /* Selection Expression */
  3434.                 gSearchMethod=2;
  3435.                 break;
  3436.             case 8:            /* Select All or Case Sensitive */
  3437.                 gCaseSensitive = !gCaseSensitive;
  3438.                 break;
  3439.             case 9:            /* Center Selection or Search Backwards */
  3440.                 gSearchBackwards = !gSearchBackwards;
  3441.                 break;
  3442.             case 10:        /* Scale to fit or Wrap-Around Search */
  3443.                 gWrapSearch = !gWrapSearch;
  3444.                 break;
  3445.             default:
  3446.                 break;
  3447.         }
  3448.     }
  3449.     CloseDialog(findDialog);
  3450.     return result;
  3451. }
  3452.  
  3453. short doReplaceDialog(void)
  3454. {
  3455.     DialogPtr replaceDialog;
  3456.     short itemHit;
  3457.     short itemType;
  3458.     Handle itemHand;
  3459.     int pau=false;
  3460.     Rect box;
  3461.     
  3462.     replaceDialog=GetNewDialog(133,(Ptr)&DlogStor,(WindowPtr)(-1));
  3463.     if(!replaceDialog) 
  3464.         FatalError();
  3465.  
  3466.     GetDItem(replaceDialog,15,&itemType,&itemHand,&box);
  3467.     SetDItem(replaceDialog,15,itemType,(Handle)doLine,&box);
  3468.     GetDItem(replaceDialog,16,&itemType,&itemHand,&box);
  3469.     SetDItem(replaceDialog,16,itemType,(Handle)doLine,&box);
  3470.     GetDItem(replaceDialog,17,&itemType,&itemHand,&box);
  3471.     SetDItem(replaceDialog,17,itemType,(Handle)doButton,&box);
  3472.  
  3473.     GetDItem(replaceDialog,4,&itemType,&itemHand,&box);
  3474.     SetIText(itemHand,gFindBuffer);
  3475.     SelIText(replaceDialog,4,0,32767);
  3476.  
  3477.     GetDItem(replaceDialog,6,&itemType,&itemHand,&box);
  3478.     SetIText(itemHand,gReplaceBuffer);
  3479.  
  3480.     while(!pau) {
  3481.         /* Initialize the three radio buttons */
  3482.         GetDItem(replaceDialog,9,&itemType,&itemHand,&box);
  3483.         SetCtlValue((ControlHandle)itemHand,gSearchMethod==0);
  3484.         GetDItem(replaceDialog,10,&itemType,&itemHand,&box);
  3485.         SetCtlValue((ControlHandle)itemHand,gSearchMethod==1);
  3486.         GetDItem(replaceDialog,11,&itemType,&itemHand,&box);
  3487.         SetCtlValue((ControlHandle)itemHand,gSearchMethod==2);
  3488.         /* Do the check boxes */
  3489.         GetDItem(replaceDialog,12,&itemType,&itemHand,&box);
  3490.         SetCtlValue((ControlHandle)itemHand,gCaseSensitive);
  3491.         GetDItem(replaceDialog,13,&itemType,&itemHand,&box);
  3492.         SetCtlValue((ControlHandle)itemHand,gSearchBackwards);
  3493.         GetDItem(replaceDialog,14,&itemType,&itemHand,&box);
  3494.         SetCtlValue((ControlHandle)itemHand,gWrapSearch);
  3495.  
  3496.         ModalDialog(DialogStandardFilter,&itemHit);
  3497.  
  3498.         switch(itemHit) {
  3499.             case 1: case 7: case 8:    /* Replace, Replace All, Find */
  3500.                 pau=true;
  3501.                 GetDItem(replaceDialog,4,&itemType,&itemHand,&box);
  3502.                 GetIText(itemHand,gFindBuffer);
  3503.                 GetDItem(replaceDialog,6,&itemType,&itemHand,&box);
  3504.                 GetIText(itemHand,gReplaceBuffer);
  3505.                 break;
  3506.             case 2:
  3507.                 pau=true;
  3508.                 break;
  3509.             case 9:            /* Literal Radio Button */
  3510.                 gSearchMethod=0;
  3511.                 break;
  3512.             case 10:        /* Entire Word */
  3513.                 gSearchMethod=1;
  3514.                 break;
  3515.             case 11:        /*  Selection Expression */
  3516.                 gSearchMethod=2;
  3517.                 break;
  3518.             case 12:        /* Case Sensitive */
  3519.                 gCaseSensitive = !gCaseSensitive;
  3520.                 break;
  3521.             case 13:        /* Search Backwards */
  3522.                 gSearchBackwards = !gSearchBackwards;
  3523.                 break;
  3524.             case 14:        /* Wrap-Around Search */
  3525.                 gWrapSearch = !gWrapSearch;
  3526.                 break;
  3527.             default:
  3528.                 SysBeep(7);
  3529.                 break;
  3530.         }
  3531.     }
  3532.     CloseDialog(replaceDialog);
  3533.     return itemHit;
  3534. }
  3535.  
  3536. char *GetSelection(WindowPtr wind,char *buf,int len)
  3537. {
  3538.     /* Returns a c string. */
  3539.     TE32KHandle tH;
  3540.     int selLen;
  3541.     
  3542.     *buf=0;
  3543.     if((tH=(TE32KHandle)((DocumentPeek)wind)->docData) && (**tH).selStart<(**tH).selEnd) {
  3544.         selLen = (**tH).selEnd-(**tH).selStart;
  3545.         HLock((**tH).hText);
  3546.         selLen=(selLen<len)?selLen:len;
  3547.         strncpy(buf,*(**tH).hText+(**tH).selStart,selLen);
  3548.         HUnlock((**tH).hText);
  3549.         *(buf+selLen)=0;
  3550.         return buf;
  3551.     }
  3552.     return 0;
  3553. }
  3554.  
  3555. void textSelectMark(WindowPtr wind,short item)
  3556. {
  3557.     TE32KHandle tH;
  3558.     short *mark;
  3559.     short i;
  3560.     
  3561.     if(tH=(TE32KHandle)((DocumentPeek)wind)->docData) {
  3562.         HLock(((DocumentPeek)wind)->marks);
  3563.         mark = (short *)*((DocumentPeek)wind)->marks;
  3564.         for(mark++,i=1;i<item;i++)
  3565.             mark+= 4+(((MarkRecPtr)mark)->label+1)/2;
  3566.         TE32KSetSelect(((MarkRecPtr)mark)->selStart,((MarkRecPtr)mark)->selEnd,tH);
  3567.         HUnlock(((DocumentPeek)wind)->marks);
  3568.         positionView(tH,1);            
  3569.         AdjustScrollBars(wind);
  3570.         SetScrollBarValues(wind);
  3571.         ((DocumentPeek)wind)->fHaveSelection = 1;        
  3572.     }
  3573. }
  3574.  
  3575. void textNewMark(WindowPtr wind)
  3576. {
  3577.     TE32KHandle tH;
  3578.     long selStart,selEnd;
  3579.     Str255 selection;
  3580.     
  3581.     if(tH=(TE32KHandle)((DocumentPeek)wind)->docData) {
  3582.         selStart=(**tH).selStart;
  3583.         selEnd=(**tH).selEnd;
  3584.         GetSelection(wind,selection,63);
  3585.         InsertMark((DocumentPeek)wind,selStart,selEnd,selection);
  3586.     }
  3587. }
  3588.  
  3589. void textUnMark(DocumentPeek doc)
  3590. {    
  3591.     TE32KHandle tH;
  3592.     long selStart,selEnd;
  3593.     
  3594.     if(doc->marks && (tH=(TE32KHandle)doc->docData)) {
  3595.         selStart=(**tH).selStart;
  3596.         selEnd=(**tH).selEnd;
  3597.         DoUnmark(doc,selStart,selEnd);
  3598.     }
  3599. }
  3600. void UpdateSizeList(WindowPtr formatDialog,short fontNum,ListHandle *sizeList) 
  3601. {
  3602.     ListHandle theList=0;
  3603.     long textSize;
  3604.     short i,nRows,lastSize;
  3605.     short itemType;
  3606.     Handle itemHand;
  3607.     Point cellSize,cell;
  3608.     Rect box,dataBounds;
  3609.     Str255 data;
  3610.     
  3611.     if(*sizeList) 
  3612.         LDispose(*sizeList);
  3613.         
  3614.     GetDItem(formatDialog,9,&itemType,&itemHand,&box);
  3615.     GetIText(itemHand,data);
  3616.     StringToNum(data,&textSize);
  3617.     
  3618.     GetDItem(formatDialog,11,&itemType,&itemHand,&box);
  3619.     InsetRect(&box,1,1);
  3620.     EraseRect(&box);
  3621.     InvalRect(&box);
  3622.  
  3623.     cellSize.v=15;
  3624.     cellSize.h=box.right-box.left;
  3625.  
  3626.     box.bottom=box.top+cellSize.v*((box.bottom-box.top)/cellSize.v);
  3627.     box.right-=15;
  3628.  
  3629.     SetRect(&dataBounds,0,0,1,0);
  3630.     *sizeList=LNew(&box,&dataBounds,cellSize,0,formatDialog,FALSE,FALSE,FALSE,TRUE);
  3631.     if(!*sizeList) {
  3632.         SysBeep(7);
  3633.         return;
  3634.     }
  3635.     
  3636.     cell.h=cell.v=0;
  3637.     nRows=0;
  3638.     i=(textSize<9)? textSize:9;
  3639.     for(;i<25;i++) {
  3640.         if(i==textSize || RealFont((short)fontNum,i)) {
  3641.             NumToString(i,data);
  3642.             LAddRow(1,nRows++,*sizeList);
  3643.             LSetCell(data+1,*data,cell,*sizeList);
  3644.             if(textSize==i) {
  3645.                 LSetSelect(true,cell,*sizeList);
  3646.                 LAutoScroll(*sizeList);
  3647.             }
  3648.             cell.v++;
  3649.         }
  3650.         if(i<8)
  3651.             i=8;
  3652.     }
  3653.     lastSize=i=(textSize>24 && textSize<30)? textSize:30;
  3654.     for(;i<97;i+=6) {
  3655.         if(i==textSize || RealFont((short)fontNum,i)) {
  3656.             NumToString(i,data);
  3657.             LAddRow(1,nRows++,*sizeList);
  3658.             LSetCell(data+1,*data,cell,*sizeList);
  3659.             if(textSize==i) {
  3660.                 LSetSelect(true,cell,*sizeList);
  3661.                 LAutoScroll(*sizeList);
  3662.             }
  3663.             cell.v++;
  3664.         } else if(textSize<i && textSize>lastSize) {
  3665.             NumToString(textSize,data);
  3666.             LAddRow(1,nRows++,*sizeList);
  3667.             LSetCell(data+1,*data,cell,*sizeList);
  3668.             LSetSelect(true,cell,*sizeList);
  3669.             LAutoScroll(*sizeList);
  3670.             cell.v++;
  3671.         }
  3672.     }
  3673. }
  3674.  
  3675. ListHandle FillFontList(WindowPtr formatDialog,short fontNum,Point *fontCell)
  3676. {
  3677.     short i,nFonts;
  3678.     ListHandle theList=0;
  3679.     MenuHandle fMenu;
  3680.     char *fonts;
  3681.     Rect box,dataBounds;
  3682.     Point cellSize,cell;
  3683.     short itemType;
  3684.     Handle itemHand;
  3685.     Str255 fontName;
  3686.     
  3687.     if(fMenu=NewMenu(2202,"")) {
  3688.     
  3689.         /* Pending more study, the MenuManager's method for building a
  3690.             list of fonts, seems most efficient. Questions: are the font
  3691.             resources left in memory? Are they in alphabetical order? */
  3692.             
  3693.         AddResMenu(fMenu,'FONT');
  3694.         nFonts = CountMItems(fMenu);
  3695.         
  3696.         GetDItem(formatDialog,10,&itemType,&itemHand,&box);
  3697.         InsetRect(&box,1,1);
  3698.     
  3699.         cellSize.v=15;
  3700.         cellSize.h=box.right-box.left;
  3701.     
  3702.         box.bottom=box.top+cellSize.v*((box.bottom-box.top)/cellSize.v);
  3703.         box.right-=15;
  3704.     
  3705.         SetRect(&dataBounds,0,0,1,nFonts);
  3706.         theList=LNew(&box,&dataBounds,cellSize,0,formatDialog,FALSE,FALSE,FALSE,TRUE);
  3707.  
  3708.         if(!theList) {
  3709.             SysBeep(7);
  3710.             DisposeMenu(fMenu);
  3711.             return 0;
  3712.         }
  3713.         
  3714.         GetFontName(fontNum,fontName);
  3715.         cell.h=0;
  3716.         cell.v=0;
  3717.         HLock((Handle)fMenu);
  3718.         fonts=(**fMenu).menuData+1;
  3719.         for(i=1;i<=nFonts;i++) {
  3720.             LSetCell(fonts+1,*fonts,cell,theList);
  3721.             if(*fontName=*fonts && !strncmp(fontName+1,fonts+1,*fonts)) {
  3722.                 *fontCell=cell;
  3723.                 LSetSelect(true,cell,theList);
  3724.                 LAutoScroll(theList);
  3725.             }
  3726.             cell.v++;
  3727.             fonts+=*fonts+5;
  3728.         }
  3729.         HUnlock((Handle)fMenu);
  3730.         DisposeMenu(fMenu);
  3731.         return theList;
  3732.     }
  3733.     return 0;
  3734. }
  3735.  
  3736. pascal Boolean formatFilter(DialogPtr dialog,EventRecord *theEvent,short *itemHit)
  3737. {
  3738.     ListHandle *lists;
  3739.     Point mouseLoc,cell;
  3740.     short modifiers;
  3741.     Rect box;
  3742.     short itemType;
  3743.     char key;
  3744.     Handle itemHand;
  3745.     Boolean selected;
  3746.     
  3747.     SetPort(dialog);
  3748.  
  3749.     cell.h=cell.v=0;
  3750.     lists=(ListHandle *)GetWRefCon(dialog);
  3751.     selected=LGetSelect(true,&cell,lists[0]);
  3752.     
  3753.     if(theEvent->what==mouseDown) {
  3754.         mouseLoc=theEvent->where;
  3755.         modifiers=theEvent->modifiers;
  3756.         GlobalToLocal(&mouseLoc);
  3757.         GetDItem(dialog,10,&itemType,&itemHand,&box);
  3758.         if(PtInRect(mouseLoc,&box)) {
  3759.             if(LClick(mouseLoc,modifiers,lists[0])) {    /* Double Click */
  3760.                 *itemHit=1;
  3761.                 return true;
  3762.             }
  3763.         }
  3764.         GetDItem(dialog,11,&itemType,&itemHand,&box);
  3765.         if(PtInRect(mouseLoc,&box)) {
  3766.             if(LClick(mouseLoc,modifiers,lists[1])) {    /* Double Click */
  3767.                 *itemHit=1;
  3768.                 return true;
  3769.             }
  3770.         }
  3771.     } else if(theEvent->what==keyDown) {
  3772.         if(DialogStandardKeyDown(dialog,theEvent,itemHit))
  3773.             return true;
  3774.         key=theEvent->message&charCodeMask;
  3775.         if(isdigit(key) || key==TAB || key==DELETE) {
  3776.             return false;
  3777.         } else
  3778.             return true;
  3779.     }
  3780.     GetDItem(dialog,1,&itemType,&itemHand,&box);
  3781.     HiliteControl((ControlHandle)itemHand,(selected)? 0:255);
  3782.     return false;
  3783. }
  3784.  
  3785. static void doFormatDialog(WindowPtr wind)
  3786. {
  3787.     TE32KHandle tH;
  3788.     DialogPtr formatDialog;
  3789.     short itemHit,itemType,dataLen,fontNum,i;
  3790.     Boolean noWordWrap,calText=false,pau=false,showInvisibles;
  3791.     Boolean autoIndent,wrapToLength,wrapText;
  3792.     Handle itemHand;
  3793.     ListHandle lists[2];
  3794.     Point fontCell,tempCell,sizeCell;
  3795.     long textSize,tabChars,lineLength;
  3796.     Rect box;
  3797.     Str255 numStr;
  3798.     
  3799.     if(tH=(TE32KHandle)((DocumentPeek)wind)->docData) {
  3800.         formatDialog=GetNewDialog(144,(Ptr)&DlogStor,(WindowPtr)(-1));
  3801.         if(!formatDialog) 
  3802.             FatalError();
  3803.     
  3804.         if(lists[0]=FillFontList(formatDialog,(**tH).txFont,&fontCell)) {
  3805.     
  3806.             noWordWrap=(**tH).crOnly;
  3807.             wrapToLength=(**tH).wrapToLength;
  3808.             autoIndent=(**tH).autoIndent;
  3809.             lineLength=((**tH).maxLineWidth==32767)? 75:(**tH).maxLineWidth;
  3810.             showInvisibles=(**tH).showInvisibles;
  3811.  
  3812.             SetWRefCon(formatDialog,(long)lists);
  3813.             LAutoScroll(lists[0]);
  3814.             UpdateList(lists[0]);
  3815.  
  3816.             GetDItem(formatDialog,19,&itemType,&itemHand,&box);
  3817.             SetDItem(formatDialog,19,itemType,(Handle)doButton,&box);
  3818.             
  3819.             GetDItem(formatDialog,18,&itemType,&itemHand,&box);
  3820.             SetDItem(formatDialog,18,itemType,(Handle)doFrame,&box);
  3821.             
  3822.             GetDItem(formatDialog,4,&itemType,&itemHand,&box);
  3823.             NumToString((**tH).tabChars,numStr);
  3824.             SetIText(itemHand,numStr);
  3825.             
  3826.             GetDItem(formatDialog,9,&itemType,&itemHand,&box);
  3827.             NumToString((**tH).txSize,numStr);
  3828.             SetIText(itemHand,numStr);
  3829.             
  3830.             GetDItem(formatDialog,15,&itemType,&itemHand,&box);
  3831.             NumToString(lineLength,numStr);
  3832.             SetIText(itemHand,numStr);
  3833.             
  3834.             lists[1]=0;
  3835. #if 0
  3836.             UpdateSizeList(formatDialog,(**tH).txFont,&lists[1]);
  3837.             LAutoScroll(lists[1]);
  3838.             UpdateList(lists[1]);
  3839. #endif
  3840.             sizeCell.v=-1;
  3841.                         
  3842.             while(!pau) {
  3843.             
  3844.                 /* Do the check boxes */
  3845.                 
  3846.                 GetDItem(formatDialog,5,&itemType,&itemHand,&box);
  3847.                 SetCtlValue((ControlHandle)itemHand,showInvisibles);
  3848.                 
  3849.                 GetDItem(formatDialog,6,&itemType,&itemHand,&box);
  3850.                 SetCtlValue((ControlHandle)itemHand,!noWordWrap);
  3851.                 
  3852.                 GetDItem(formatDialog,16,&itemType,&itemHand,&box);
  3853.                 SetCtlValue((ControlHandle)itemHand,autoIndent);
  3854.                 
  3855.                 /* Do the radio buttons */
  3856.                 
  3857.                 GetDItem(formatDialog,12,&itemType,&itemHand,&box);
  3858.                 SetCtlValue((ControlHandle)itemHand,!wrapToLength);
  3859.                 HiliteControl((ControlHandle)itemHand,(noWordWrap)?255:0);
  3860.                 
  3861.                 GetDItem(formatDialog,13,&itemType,&itemHand,&box);
  3862.                 SetCtlValue((ControlHandle)itemHand,wrapToLength);
  3863.                 HiliteControl((ControlHandle)itemHand,(noWordWrap)?255:0);
  3864.  
  3865.                 tempCell=LLastClick(lists[0]);
  3866.                 if(tempCell.v!=fontCell.v) {
  3867.                     fontCell=tempCell;
  3868.                     dataLen=255;
  3869.                     LGetCell(numStr+1,&dataLen,fontCell,lists[0]);
  3870.                     *numStr=dataLen;
  3871.                     GetFNum(numStr,&fontNum);
  3872.                     UpdateSizeList(formatDialog,fontNum,&lists[1]);
  3873.                     LAutoScroll(lists[1]);
  3874.                     UpdateList(lists[1]);
  3875.                 }
  3876.                 ModalDialog(formatFilter,&itemHit);
  3877.         
  3878.                 switch(itemHit) {
  3879.                     case 1:
  3880.                         GetDItem(formatDialog,4,&itemType,&itemHand,&box);
  3881.                         GetIText(itemHand,numStr);
  3882.                         StringToNum(numStr,&tabChars);
  3883.                         GetDItem(formatDialog,15,&itemType,&itemHand,&box);
  3884.                         GetIText(itemHand,numStr);
  3885.                         StringToNum(numStr,&lineLength);
  3886.                         
  3887.                         if(tabChars>0 && lineLength>0) {
  3888.                             pau=true;
  3889.                             (**tH).tabChars=tabChars;
  3890.                             (**tH).tabWidth=tabChars * (**tH).theCharWidths[' '];
  3891.                         } else {
  3892.                             SelIText(formatDialog,4,0,32767);
  3893.                             SysBeep(7);
  3894.                         }
  3895.                         break;
  3896.                     case 2:
  3897.                         LDispose(lists[0]);
  3898.                         LDispose(lists[1]);
  3899.                         CloseDialog(formatDialog);
  3900.                         return;
  3901.                     case 5:            /* Show Invisibles */
  3902.                         showInvisibles=!showInvisibles;
  3903.                         break;
  3904.                     case 6:            /* Word Wrap */
  3905.                         noWordWrap=!noWordWrap;
  3906.                         break;
  3907.                     case 11:
  3908.                         tempCell.h=tempCell.v=0;
  3909.                         if(LGetSelect(true,&tempCell,lists[1])) {
  3910.                             sizeCell=tempCell;
  3911.                             dataLen=255;
  3912.                             LGetCell(numStr+1,&dataLen,sizeCell,lists[1]);
  3913.                             *numStr=dataLen;
  3914.                             GetDItem(formatDialog,9,&itemType,&itemHand,&box);
  3915.                             SetIText(itemHand,numStr);
  3916.                             SelIText(formatDialog,9,0,32767);
  3917.                         }
  3918.                         break;
  3919.                     case 12:
  3920.                         wrapToLength=0;
  3921.                         break;
  3922.                     case 13:
  3923.                         wrapToLength=1;
  3924.                         break;
  3925.                     case 16:
  3926.                         autoIndent=!autoIndent;
  3927.                         break;
  3928.                     default:
  3929.                         break;
  3930.                 }
  3931.             }
  3932.             
  3933.             tempCell.h=tempCell.v=0;
  3934.             fontNum=(**tH).txFont;
  3935.             if(LGetSelect(true,&tempCell,lists[0])) {
  3936.                 dataLen=255;
  3937.                 LGetCell(numStr+1,&dataLen,tempCell,lists[0]);
  3938.                 *numStr=dataLen;
  3939.                 GetFNum(numStr,&fontNum);
  3940.             }
  3941.             
  3942.             GetDItem(formatDialog,9,&itemType,&itemHand,&box);
  3943.             GetIText(itemHand,numStr);
  3944.             StringToNum(numStr,&textSize);            
  3945.  
  3946.             LDispose(lists[0]);
  3947.             LDispose(lists[1]);
  3948.             CloseDialog(formatDialog);
  3949.             
  3950.             if((**tH).txFont!=fontNum || (**tH).txSize!=textSize) {
  3951.                 calText=true;
  3952.                 TE32KSetFontStuff(fontNum,(**tH).txFace,(**tH).txMode,(short)textSize,tH);
  3953.             }
  3954.             
  3955.             (**tH).autoIndent=autoIndent;
  3956.             wrapText = noWordWrap!=(**tH).crOnly 
  3957.                             || wrapToLength!=(**tH).wrapToLength
  3958.                             || (wrapToLength && (**tH).maxLineWidth!=lineLength);
  3959.                             
  3960.             (**tH).maxLineWidth=lineLength;
  3961.             
  3962.             if(calText || (**tH).showInvisibles!=showInvisibles || wrapText) {
  3963.                 SetPort(formatDialog);
  3964.                 TextFont((**tH).txFont);
  3965.                 TextFace((**tH).txFace);
  3966.                 TextSize((**tH).txSize);
  3967.                 TextMode((**tH).txMode);
  3968.                 (**tH).showInvisibles=showInvisibles;
  3969.                 if(showInvisibles) {
  3970.                     for(i=0;i<0x20;i++)
  3971.                         (**tH).theCharWidths[i] = CharWidth((unsigned char) '¿');
  3972.                     (**tH).theCharWidths[' '] = CharWidth((unsigned char) '◊');
  3973.                 } else {
  3974.                     for(i=0;i<0x21;i++)
  3975.                         (**tH).theCharWidths[i] = CharWidth((unsigned char) i);
  3976.                 }
  3977.  
  3978.                 if(!noWordWrap || noWordWrap!=(**tH).crOnly) 
  3979.                     SetCtlValue(((DocumentPeek)wind)->hScroll,0);
  3980.                     
  3981.                 (**tH).crOnly=noWordWrap;
  3982.                 (**tH).wrapToLength=wrapToLength;
  3983.                 SetTERect(wind);
  3984.                 TE32KCalText(tH);
  3985.                 TE32KSetSelect((**tH).selStart,(**tH).selEnd,tH);
  3986.                 AdjustScrollBars(wind);
  3987.                 SetScrollBarValues(wind);
  3988.                 ((DocumentPeek)wind)->fNeedtoSave=true;
  3989.  
  3990.                 SetPort(wind);
  3991.                 GetContentRect(wind,&box);
  3992.                 InvalRect(&box);
  3993.                 EraseRect(&box);
  3994.             }
  3995.         }
  3996.     }
  3997. }
  3998.  
  3999. Boolean textDoDocMenuCommand(WindowPtr wind, short menuID, short menuItem, short modifiers)
  4000. {
  4001.     short dialogItem;
  4002.     
  4003.     if(doDocMenuCommand(wind,menuID,menuItem,0))
  4004.         return true;
  4005.     
  4006.     switch(menuID) {
  4007.         case EDIT_ID:
  4008.             switch(menuItem) {
  4009.                 case iFormat: 
  4010.                     doFormatDialog(wind);
  4011.                     break;
  4012.                 case iAlign:
  4013.                     EnTabAndShift(wind,0);
  4014.                     break;
  4015.                 case iShiftRight:
  4016.                     EnTabAndShift(wind,1);
  4017.                     break;
  4018.                 case iShiftLeft:
  4019.                     EnTabAndShift(wind,-1);
  4020.                     break;
  4021.             }
  4022.             break;
  4023.         case FIND_ID:
  4024.             switch(menuItem) {
  4025.                 case iFind:
  4026.                     if(doFindDialog(138))
  4027.                         findSearchString(wind,modifiers&shiftKey);
  4028.                     break;
  4029.                 case iFindSame:
  4030.                     findSearchString(wind,modifiers&shiftKey);
  4031.                     break;
  4032.                 case iFindSelection:
  4033.                     GetSelection(wind,gFindBuffer,255);
  4034.                     c2pstr(gFindBuffer);
  4035.                     if(gSearchMethod==2)
  4036.                         gSearchMethod=0;
  4037.                     findSearchString(wind,modifiers&shiftKey);
  4038.                     break;
  4039.                 case iDisplaySelection:
  4040.                     positionView((TE32KHandle)((DocumentPeek)wind)->docData,1);
  4041.                     AdjustScrollBars(wind);
  4042.                     SetScrollBarValues(wind);
  4043.                     break;
  4044.                 case iReplace:
  4045.                     switch (dialogItem=doReplaceDialog()) {
  4046.                         case 1:            /* Replace */
  4047.                             if(findSearchString(wind,modifiers&shiftKey)) {
  4048.                                 TE32KDelete((TE32KHandle)((DocumentPeek)wind)->docData);
  4049.                                 TE32KInsert(gReplaceBuffer+1,(long)*gReplaceBuffer+1,(TE32KHandle)((DocumentPeek)wind)->docData);
  4050.                                 ((DocumentPeek)wind)->fNeedtoSave=true;
  4051.                             }
  4052.                             break;
  4053.                         case 7:            /* Replace All */
  4054.                             while(findSearchString(wind,modifiers&shiftKey)) {
  4055.                                 TE32KDelete((TE32KHandle)((DocumentPeek)wind)->docData);
  4056.                                 TE32KInsert(gReplaceBuffer+1,(long)*gReplaceBuffer+1,(TE32KHandle)((DocumentPeek)wind)->docData);
  4057.                                 ((DocumentPeek)wind)->fNeedtoSave=true;
  4058.                             }
  4059.                             break;
  4060.                         case 8:            /* Find */
  4061.                             findSearchString(wind,modifiers&shiftKey);
  4062.                             break;
  4063.                         default:
  4064.                             break;
  4065.                     }
  4066.                     return true;
  4067.                 case iReplaceSame:
  4068.                     if(findSearchString(wind,modifiers&shiftKey)) {
  4069.                         TE32KDelete((TE32KHandle)((DocumentPeek)wind)->docData);
  4070.                         TE32KInsert(gReplaceBuffer+1,(long)*gReplaceBuffer,(TE32KHandle)((DocumentPeek)wind)->docData);
  4071.                         ((DocumentPeek)wind)->fNeedtoSave=true;
  4072.                     }
  4073.                     return true;
  4074.                 default:
  4075.                     break;
  4076.             }
  4077.             break;
  4078.         case MARK_ID:
  4079.             if(menuItem==iMark) {    
  4080.                 textNewMark(wind);
  4081.             } else if(menuItem==iUnmark) {
  4082.                 textUnMark((DocumentPeek)wind);
  4083.             } else if(menuItem==iAlphabetical) 
  4084.                 return false;
  4085.             else 
  4086.                 textSelectMark(wind,menuItem-4);
  4087.             return true;
  4088.         case CONVERT_ID:
  4089.             switch (menuItem) {
  4090.                 case iStr2Curly:
  4091.                     StraightToCurly(wind);
  4092.                     return true;
  4093.                 case iCurly2Str:
  4094.                     CurlyToStraight(wind);
  4095.                     return true;
  4096.                 case iAddLf:
  4097.                     AddLinefeeds(wind);
  4098.                     return true;
  4099.                 case iStripLf:
  4100.                     StripLinefeeds(wind);
  4101.                     return true;
  4102.                 case iCRtoLF:
  4103.                     ReturnstoLinefeeds(wind);
  4104.                     return true;
  4105.                 case iLFtoCR:
  4106.                     LinefeedstoReturns(wind);
  4107.                     return true;
  4108.                 case iFormParagraphs:
  4109.                     FormParagraphs(wind);
  4110.                     return true;
  4111.                 case iWWtoWindow:
  4112.                     WordWrap(wind,false);
  4113.                     return true;
  4114.                 case iWWtoLength:
  4115.                     WordWrap(wind,true);
  4116.                     return true;
  4117.                 case iTabstoSpaces:
  4118.                     TabsToSpaces(wind);
  4119.                     return true;
  4120.                 case iSpacestoTabs:
  4121.                     SpacesToTabs(wind);
  4122.                     return true;
  4123.                 default:
  4124.                     break;
  4125.             }
  4126.             break;
  4127.         default:
  4128.             break;
  4129.     }
  4130.     return false;
  4131. }
  4132.  
  4133. short textGetVertPageScrollAmount(WindowPtr wind)
  4134. {
  4135.     Rect r;
  4136.     short lineHeight;
  4137.     
  4138.     lineHeight = (**(TE32KHandle)((DocumentPeek)wind)->docData).lineHeight;
  4139.     GetContentRect(wind,&r);
  4140.     return ((r.bottom - r.top)/lineHeight - 1);
  4141. }
  4142.     
  4143. void textAdjustScrollBars(WindowPtr wind)
  4144. {
  4145.     DocumentPeek doc;
  4146.     Rect r;
  4147.     short dh,dv,lineHeight;
  4148.     short currentValue;
  4149.     short newMax;
  4150.     RgnHandle oldClip;
  4151.     
  4152.     doc = (DocumentPeek)wind;
  4153.     GetContentRect(wind,&r);
  4154.     dh=dv=0;
  4155.     if(doc->vScroll) {
  4156.         currentValue=GetCtlValue(doc->vScroll);
  4157.         lineHeight = (**(TE32KHandle)doc->docData).lineHeight;
  4158.         newMax = GetVertSize(wind) - 2;
  4159.         if(newMax<0)
  4160.             newMax=0;
  4161.         if(currentValue>newMax)
  4162.             dv = currentValue - newMax;
  4163.         SetCtlMax(doc->vScroll,newMax);
  4164.     }
  4165.     if(doc->hScroll) {
  4166.         currentValue=GetCtlValue(doc->hScroll);
  4167.         newMax = GetHorizSize(wind) - (r.right - r.left);
  4168.         if(newMax<0)
  4169.             newMax=0;
  4170.         if(currentValue>newMax)
  4171.             dh = currentValue - newMax;
  4172.         SetCtlMax(doc->hScroll,newMax);
  4173.     }
  4174.     FocusOnContent(wind);
  4175.     if(dh | dv) {
  4176.         InvalRect(&r);
  4177.         /* Shut down clip region to empty rectangle before calling
  4178.             ScrollContents. */
  4179.         oldClip = NewRgn();
  4180.         if(MemError()) {
  4181.             doMessage(1);
  4182.             return;
  4183.         }
  4184.         GetClip(oldClip);
  4185.         SetRect(&r,0,0,0,0);
  4186.         ClipRect(&r);
  4187.         ScrollContents(wind,dh,dv);
  4188.         SetClip(oldClip);
  4189.         DisposeRgn(oldClip);
  4190.     }
  4191. }
  4192.  
  4193. void textDoUndo(WindowPtr wind)
  4194. {
  4195.     long selStart,selEnd,delta=0;
  4196.     TE32KHandle tH;
  4197.     
  4198.     if(((DocumentPeek)wind)->docData) {
  4199.         tH = (TE32KHandle)((DocumentPeek)wind)->docData;
  4200.         selStart = (**tH).undoStart;
  4201.         selEnd = (**tH).undoEnd;
  4202.         if(selStart<selEnd) 
  4203.             delta=selStart-selEnd;
  4204.         if((**tH).undoBuf)
  4205.             delta+=GetHandleSize((**tH).undoBuf);
  4206.         TE32KUndo(tH);
  4207.         UpdateMarks((DocumentPeek)wind,selStart,selEnd,delta,(**tH).teLength);
  4208.         ((DocumentPeek)wind)->fHaveSelection = SetSelectionFlag(tH);
  4209.         AdjustScrollBars(wind);
  4210.         SetScrollBarValues(wind);
  4211.     }
  4212. }
  4213.  
  4214. void textDoCut(WindowPtr wind)
  4215. {
  4216.     long selStart,selEnd;
  4217.     TE32KHandle tH;
  4218.  
  4219.     tH = (TE32KHandle)((DocumentPeek)wind)->docData;
  4220.     selStart = (**tH).selStart;
  4221.     selEnd = (**tH).selEnd;
  4222.     TE32KCut(tH);
  4223.     ((DocumentPeek)wind)->fNeedtoSave=true;
  4224.     UpdateMarks((DocumentPeek)wind,selStart,selEnd,selStart-selEnd,(**tH).teLength);
  4225.     (**tH).undoDelta = selStart-selEnd;
  4226.     AdjustScrollBars(wind);
  4227.     SetScrollBarValues(wind);
  4228.     if(gClipboardDoc) {
  4229.         tH=(TE32KHandle)gClipboardDoc->docData;
  4230.         TE32KSetSelect(0L,(**tH).teLength,tH);
  4231.         TE32KDelete(tH);
  4232.         TE32KPaste((TE32KHandle)gClipboardDoc->docData);
  4233.         AdjustScrollBars((WindowPtr)gClipboardDoc);
  4234.         SetScrollBarValues((WindowPtr)gClipboardDoc);
  4235.     }
  4236. }
  4237.  
  4238. void textDoPaste(WindowPtr wind)
  4239. {
  4240.     long selStart,selEnd,delta;
  4241.     TE32KHandle tH;
  4242.     
  4243.     tH = (TE32KHandle)((DocumentPeek)wind)->docData;
  4244.     selStart = (**tH).selStart;
  4245.     selEnd = (**tH).selEnd;
  4246.     TE32KPaste(tH);
  4247.     delta=selStart-selEnd;    /* -length of cut string */
  4248.     /* plus length of replacement string */
  4249.     delta+=TE32KScrpLength;
  4250.     UpdateMarks((DocumentPeek)wind,selStart,selEnd,delta,(**tH).teLength);
  4251.     (**tH).undoDelta=delta;
  4252.     ((DocumentPeek)wind)->fNeedtoSave=true;
  4253.     ((DocumentPeek)wind)->fHaveSelection = SetSelectionFlag(tH);
  4254.     TE32KSelView(tH);
  4255.     AdjustScrollBars(wind);
  4256.     SetScrollBarValues(wind);
  4257. }
  4258.  
  4259. void textDoClear(WindowPtr wind)
  4260. {
  4261.     long selStart,selEnd;
  4262.     TE32KHandle tH;
  4263.     
  4264.     tH = (TE32KHandle)((DocumentPeek)wind)->docData;
  4265.     selStart = (**tH).selStart;
  4266.     selEnd = (**tH).selEnd;
  4267.     TE32KDelete(tH);
  4268.     
  4269.     ((DocumentPeek)wind)->fNeedtoSave=true;
  4270.     UpdateMarks((DocumentPeek)wind,selStart,selEnd,selStart-selEnd,(**tH).teLength);
  4271.     TE32KSelView(tH);
  4272.     AdjustScrollBars(wind);
  4273.     SetScrollBarValues(wind);
  4274. }
  4275.  
  4276. void textDoCopy(WindowPtr wind)
  4277. {
  4278.     TE32KHandle tH;
  4279.     
  4280.     TE32KCopy((TE32KHandle)((DocumentPeek)wind)->docData);
  4281.     if(gClipboardDoc) {
  4282.         tH=(TE32KHandle)gClipboardDoc->docData;
  4283.         TE32KSetSelect(0L,(**tH).teLength,tH);
  4284.         TE32KDelete(tH);
  4285.         TE32KPaste((TE32KHandle)gClipboardDoc->docData);
  4286.         if((**tH).caretState)
  4287.             xorCaret(tH);
  4288.         AdjustScrollBars((WindowPtr)gClipboardDoc);
  4289.         SetScrollBarValues((WindowPtr)gClipboardDoc);
  4290.     }
  4291. }
  4292.  
  4293. void textSelectAll(WindowPtr wind)
  4294. {
  4295.     TE32KHandle tH;
  4296.     if(tH=(TE32KHandle)((DocumentPeek)wind)->docData) {
  4297.         TE32KSetSelect(0L,(**tH).teLength,tH);
  4298.         ((DocumentPeek)wind)->fHaveSelection = SetSelectionFlag(tH);
  4299.     }
  4300. }
  4301.  
  4302. void AddTextMemberFunctions(DocumentPeek doc)
  4303. {
  4304.     doc->makeWindow=textMakeWindow;
  4305.     doc->initDoc=textInitDoc;
  4306.     doc->destructor=textDestructor;
  4307.     doc->openDocFile=textOpenDocFile;
  4308.     doc->readDocFile=textReadDocFile;
  4309.     doc->writeDocFile=textWriteDocFile;
  4310.     doc->writeDocResourceFork=textWriteDocResourceFork;
  4311.     doc->fDocType='TEXT';
  4312.     doc->draw=textDraw;
  4313.     doc->doPageSetup=DoPageSetup;
  4314.     doc->doPrint=textDoPrint;
  4315.     doc->activate=textActivate;
  4316.     doc->deactivate=textDeactivate;
  4317.     doc->doContent=textDoContent;
  4318.     doc->doKeyDown=textDoKeyDown;
  4319.     doc->doIdle=textDoIdle;
  4320.     doc->doGrow=textDoGrow;
  4321.     doc->doZoom=textDoZoom;
  4322.     doc->doUndo=textDoUndo;
  4323.     doc->doCut=textDoCut;
  4324.     doc->doPaste=textDoPaste;
  4325.     doc->doClear=textDoClear;
  4326.     doc->doCopy=textDoCopy;
  4327.     doc->doSelectAll=textSelectAll;
  4328.     doc->adjustCursor=textAdjustCursor;
  4329.     doc->adjustScrollBars=textAdjustScrollBars;
  4330.     doc->setScrollBarValues=textSetScrollBarValues;
  4331.     doc->getContentRect=textGetContentRect;
  4332.     doc->getHorizSize=textGetHorizSize;
  4333.     doc->getVertSize=textGetVertSize;
  4334.     doc->getVertPageScrollAmount=textGetVertPageScrollAmount;
  4335. /*    doc->getHorizPageScrollAmount=textGetHorizPageScrollAmount;    */
  4336.     doc->scrollContents=textScrollContents;
  4337.     doc->getVertLineScrollAmount=textGetVertLineScrollAmount;
  4338.     doc->getHorizLineScrollAmount=textGetHorizLineScrollAmount;
  4339.     doc->adjustDocMenus=textAdjustDocMenus;
  4340.     doc->doDocMenuCommand=textDoDocMenuCommand;
  4341. }
  4342.